Read programmer serial number from libusb or hidusb (#1223)

* Silence compiler warnings

* Fix a fall-through error in switch

* Slightly reformat programmer info printout
Now the target voltage is printed out along with the HW version, FW version and serial number, and they all allign nicely. When in ISP mode, the "SCK period" value is printed _after_ the target voltage readout, and _before_ the additional clocks the programmer holds, such as JTAG, PDI and UPDI clocks.

Co-authored-by: Stefan Rueger <stefan.rueger@urclocks.com>
This commit is contained in:
Hans 2022-12-21 20:11:31 +01:00 committed by GitHub
parent a696c94d8f
commit c991ae9739
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 191 additions and 95 deletions

View File

@ -104,6 +104,7 @@ static int jtag3_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM
static int jtag3_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, static int jtag3_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
unsigned long addr, unsigned char data); unsigned long addr, unsigned char data);
static int jtag3_set_sck_period(const PROGRAMMER *pgm, double v); static int jtag3_set_sck_period(const PROGRAMMER *pgm, double v);
void jtag3_display(const PROGRAMMER *pgm, const char *p);
void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp); void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp);
static int jtag3_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m, static int jtag3_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
unsigned int page_size, unsigned int page_size,
@ -188,7 +189,7 @@ static bool matches(const char *s, const char *pat)
static void jtag3_print_data(unsigned char *b, size_t s) static void jtag3_print_data(unsigned char *b, size_t s)
{ {
int i; size_t i;
if (s < 2) if (s < 2)
return; return;
@ -205,9 +206,9 @@ static void jtag3_print_data(unsigned char *b, size_t s)
} }
static void jtag3_prmsg(const PROGRAMMER *pgm, unsigned char *data, size_t len) { static void jtag3_prmsg(const PROGRAMMER *pgm, unsigned char *data, size_t len) {
int i;
if (verbose >= 4) { if (verbose >= 4) {
size_t i;
msg_trace("Raw message:\n"); msg_trace("Raw message:\n");
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
@ -302,7 +303,7 @@ static void jtag3_prmsg(const PROGRAMMER *pgm, unsigned char *data, size_t len)
case RSP3_INFO: case RSP3_INFO:
msg_info("Info returned:\n"); msg_info("Info returned:\n");
for (i = 2; i < len; i++) { for (size_t i = 2; i < len; i++) {
if (isprint(data[i])) if (isprint(data[i]))
msg_info("%c", data[i]); msg_info("%c", data[i]);
else else
@ -336,9 +337,9 @@ static int jtag3_errcode(int reason)
} }
static void jtag3_prevent(const PROGRAMMER *pgm, unsigned char *data, size_t len) { static void jtag3_prevent(const PROGRAMMER *pgm, unsigned char *data, size_t len) {
int i;
if (verbose >= 4) { if (verbose >= 4) {
size_t i;
msg_trace("Raw event:\n"); msg_trace("Raw event:\n");
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
@ -468,6 +469,7 @@ static int jtag3_edbg_send(const PROGRAMMER *pgm, unsigned char *data, size_t le
/* 4 bytes overhead for CMD, fragment #, and length info */ /* 4 bytes overhead for CMD, fragment #, and length info */
int max_xfer = pgm->fd.usb.max_xfer; int max_xfer = pgm->fd.usb.max_xfer;
int nfragments = (len + max_xfer - 1) / max_xfer; int nfragments = (len + max_xfer - 1) / max_xfer;
if (nfragments > 1) { if (nfragments > 1) {
pmsg_debug("jtag3_edbg_send(): fragmenting into %d packets\n", nfragments); pmsg_debug("jtag3_edbg_send(): fragmenting into %d packets\n", nfragments);
@ -484,18 +486,26 @@ static int jtag3_edbg_send(const PROGRAMMER *pgm, unsigned char *data, size_t le
if (frag == 0) { if (frag == 0) {
/* Only first fragment has TOKEN and seq#, thus four bytes /* Only first fragment has TOKEN and seq#, thus four bytes
* less payload than subsequent fragments. */ * less payload than subsequent fragments. */
this_len = len < max_xfer - 8? len: max_xfer - 8; this_len = (int) len < max_xfer - 8? (int) len: max_xfer - 8;
buf[2] = (this_len + 4) >> 8; buf[2] = (this_len + 4) >> 8;
buf[3] = (this_len + 4) & 0xff; 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);
if(this_len < 0) {
pmsg_error("unexpected this_len = %d\n", this_len);
return -1;
}
memcpy(buf + 8, data, this_len); memcpy(buf + 8, data, this_len);
} }
else { else {
this_len = len < max_xfer - 4? len: max_xfer - 4; this_len = (int) len < max_xfer - 4? (int) len: max_xfer - 4;
buf[2] = (this_len) >> 8; buf[2] = (this_len) >> 8;
buf[3] = (this_len) & 0xff; buf[3] = (this_len) & 0xff;
if(this_len < 0) {
pmsg_error("unexpected this_len = %d\n", this_len);
return -1;
}
memcpy(buf + 4, data, this_len); memcpy(buf + 4, data, this_len);
} }
@ -640,7 +650,7 @@ static int jtag3_recv_frame(const PROGRAMMER *pgm, unsigned char **msg) {
if (pgm->flag & PGM_FL_IS_EDBG) if (pgm->flag & PGM_FL_IS_EDBG)
return jtag3_edbg_recv_frame(pgm, msg); return jtag3_edbg_recv_frame(pgm, msg);
pmsg_trace("jtag3_recv():\n"); pmsg_trace("jtag3_recv_frame():\n");
if ((buf = malloc(pgm->fd.usb.max_xfer)) == NULL) { if ((buf = malloc(pgm->fd.usb.max_xfer)) == NULL) {
pmsg_error("out of memory\n"); pmsg_error("out of memory\n");
@ -653,7 +663,7 @@ static int jtag3_recv_frame(const PROGRAMMER *pgm, unsigned char **msg) {
if (rv < 0) { if (rv < 0) {
/* timeout in receive */ /* timeout in receive */
pmsg_notice2("jtag3_recv(): timeout receiving packet\n"); pmsg_notice2("jtag3_recv_frame(): timeout receiving packet\n");
free(buf); free(buf);
return -1; return -1;
} }
@ -794,6 +804,11 @@ int jtag3_recv(const PROGRAMMER *pgm, unsigned char **msg) {
* original pointer though, as the caller must free() it. * original pointer though, as the caller must free() it.
*/ */
rv -= 3; rv -= 3;
if (rv < 0) {
pmsg_error("unexpected return value %d from jtag3_recv_frame()\n", rv);
free(*msg);
return -1;
}
memmove(*msg, *msg + 3, rv); memmove(*msg, *msg + 3, rv);
return rv; return rv;
@ -817,6 +832,8 @@ int jtag3_command(const PROGRAMMER *pgm, unsigned char *cmd, unsigned int cmdlen
if (status <= 0) { if (status <= 0) {
msg_notice2("\n"); msg_notice2("\n");
pmsg_notice2("%s command: timeout/error communicating with programmer (status %d)\n", descr, status); pmsg_notice2("%s command: timeout/error communicating with programmer (status %d)\n", descr, status);
if (status == 0)
free(*resp);
return LIBAVRDUDE_GENERAL_FAILURE; return LIBAVRDUDE_GENERAL_FAILURE;
} else if (verbose >= 3) { } else if (verbose >= 3) {
msg_info("\n"); msg_info("\n");
@ -1525,7 +1542,7 @@ int jtag3_open_common(PROGRAMMER *pgm, const char *port) {
} }
} }
} }
pmsg_error("did not find any device matching VID 0x%04x and PID list: ", pmsg_error("no device found matching VID 0x%04x and PID list: ",
(unsigned) pinfo.usbinfo.vid); (unsigned) pinfo.usbinfo.vid);
int notfirst = 0; int notfirst = 0;
for (usbpid = lfirst(pgm->usbpid); usbpid != NULL; usbpid = lnext(usbpid)) { for (usbpid = lfirst(pgm->usbpid); usbpid != NULL; usbpid = lnext(usbpid)) {
@ -1534,6 +1551,11 @@ int jtag3_open_common(PROGRAMMER *pgm, const char *port) {
msg_error("0x%04x", (unsigned int)(*(int *)(ldata(usbpid)))); msg_error("0x%04x", (unsigned int)(*(int *)(ldata(usbpid))));
notfirst = 1; notfirst = 1;
} }
char *serno;
if ((serno = strchr(port, ':')))
msg_error(" with SN %s", ++serno);
msg_error("\n"); msg_error("\n");
return -1; return -1;
@ -1546,6 +1568,9 @@ int jtag3_open_common(PROGRAMMER *pgm, const char *port) {
pmsg_notice("found CMSIS-DAP compliant device, using EDBG protocol\n"); pmsg_notice("found CMSIS-DAP compliant device, using EDBG protocol\n");
} }
// Get USB serial number
pgm->usbsn = serial_serno();
/* /*
* drain any extraneous input * drain any extraneous input
*/ */
@ -1860,13 +1885,19 @@ static int jtag3_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AVRME
if ((status = jtag3_command(pgm, cmd, 12, &resp, "read memory")) < 0) if ((status = jtag3_command(pgm, cmd, 12, &resp, "read memory")) < 0)
return -1; return -1;
if (resp[1] != RSP3_DATA || if (resp[1] != RSP3_DATA || status < (int) block_size + 4) {
status < block_size + 4) {
pmsg_error("wrong/short reply to read memory command\n"); pmsg_error("wrong/short reply to read memory command\n");
serial_recv_timeout = otimeout; serial_recv_timeout = otimeout;
free(resp); free(resp);
return -1; return -1;
} }
if(status < 4) {
pmsg_error("unexpected response from read memory jtag3_command()\n");
free(resp);
return -1;
}
memcpy(m->buf + addr, resp + 3, status - 4); memcpy(m->buf + addr, resp + 3, status - 4);
free(resp); free(resp);
} }
@ -2028,7 +2059,7 @@ static int jtag3_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM
return status; return status;
if (resp[1] != RSP3_DATA || if (resp[1] != RSP3_DATA ||
status < (pagesize? pagesize: 1) + 4) { status < (int) (pagesize? pagesize: 1) + 4) {
pmsg_error("wrong/short reply to read memory command\n"); pmsg_error("wrong/short reply to read memory command\n");
free(resp); free(resp);
return -1; return -1;
@ -2216,6 +2247,11 @@ int jtag3_getparm(const PROGRAMMER *pgm, unsigned char scope,
} }
status -= 3; status -= 3;
if (status < 0) {
pmsg_error("unexpected return value %d from jtag3_command()\n", status);
free(resp);
return -1;
}
memcpy(value, resp + 3, (length < status? length: status)); memcpy(value, resp + 3, (length < status? length: status));
free(resp); free(resp);
@ -2253,7 +2289,7 @@ int jtag3_setparm(const PROGRAMMER *pgm, unsigned char scope,
status = jtag3_command(pgm, buf, length + 6, &resp, descr); status = jtag3_command(pgm, buf, length + 6, &resp, descr);
free(buf); free(buf);
if (status > 0) if (status >= 0)
free(resp); free(resp);
return status; return status;
@ -2304,10 +2340,10 @@ int jtag3_set_vtarget(const PROGRAMMER *pgm, double v) {
return 0; return 0;
} }
static void jtag3_display(const PROGRAMMER *pgm, const char *p) { void jtag3_display(const PROGRAMMER *pgm, const char *p) {
unsigned char parms[5]; unsigned char parms[5];
unsigned char cmd[4], *resp, c; unsigned char *resp = NULL;
int status; const char *sn;
/* /*
* Ask for: * Ask for:
@ -2319,13 +2355,21 @@ static void jtag3_display(const PROGRAMMER *pgm, const char *p) {
if (jtag3_getparm(pgm, SCOPE_GENERAL, 0, PARM3_HW_VER, parms, 5) < 0) if (jtag3_getparm(pgm, SCOPE_GENERAL, 0, PARM3_HW_VER, parms, 5) < 0)
return; return;
// Use serial number pulled from the USB driver. If not present, query the programmer
if (pgm->usbsn && *pgm->usbsn)
sn = pgm->usbsn;
else {
unsigned char cmd[4], c;
int status;
cmd[0] = SCOPE_INFO; cmd[0] = SCOPE_INFO;
cmd[1] = CMD3_GET_INFO; cmd[1] = CMD3_GET_INFO;
cmd[2] = 0; cmd[2] = 0;
cmd[3] = CMD3_INFO_SERIAL; cmd[3] = CMD3_INFO_SERIAL;
if ((status = jtag3_command(pgm, cmd, 4, &resp, "get info (serial number)")) < 0) if ((status = jtag3_command(pgm, cmd, 4, &resp, "get info (serial number)")) < 0) {
free(resp);
return; return;
}
c = resp[1]; c = resp[1];
if (c != RSP3_INFO) { if (c != RSP3_INFO) {
@ -2333,24 +2377,31 @@ static void jtag3_display(const PROGRAMMER *pgm, const char *p) {
free(resp); free(resp);
return; return;
} }
if (status < 3) {
msg_error("unexpected response from CMD3_GET_INFO command\n");
free(resp);
return;
}
memmove(resp, resp + 3, status - 3); memmove(resp, resp + 3, status - 3);
resp[status - 3] = 0; resp[status - 3] = 0;
sn = (const char*)resp;
}
msg_info("%sICE HW version : %d\n", p, parms[0]); msg_info("%sICE HW version : %d\n", p, parms[0]);
msg_info("%sICE FW version : %d.%02d (rel. %d)\n", p, parms[1], parms[2], msg_info("%sICE FW version : %d.%02d (rel. %d)\n", p, parms[1], parms[2],
(parms[3] | (parms[4] << 8))); (parms[3] | (parms[4] << 8)));
msg_info("%sSerial number : %s", p, resp); msg_info("%sSerial number : %s", p, sn);
free(resp); free(resp);
} }
void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp) { void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp) {
unsigned char prog_mode[2];
unsigned char buf[3]; unsigned char buf[3];
if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_VTARGET, buf, 2) < 0) if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_VTARGET, buf, 2) < 0)
return; return;
fmsg_out(fp, "%sVtarget %s: %.2f V\n", p, msg_info("%sVtarget : %.2f V\n", p, b2_to_u16(buf)/1000.0);
verbose? "": " ", b2_to_u16(buf)/1000.0);
// Print features unique to the Power Debugger // Print features unique to the Power Debugger
for(LNODEID ln=lfirst(pgm->id); ln; ln=lnext(ln)) { for(LNODEID ln=lfirst(pgm->id); ln; ln=lnext(ln)) {
@ -2361,8 +2412,7 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp) {
if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_VADJUST, buf, 2) < 0) if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_VADJUST, buf, 2) < 0)
return; return;
analog_raw_data = b2_to_u16(buf); analog_raw_data = b2_to_u16(buf);
fmsg_out(fp, "%sVout set %s: %.2f V\n", p, fmsg_out(fp, "%sVout set : %.2f V\n", p, analog_raw_data / 1000.0);
verbose? "": " ", analog_raw_data / 1000.0);
// Read measured generator voltage value (VOUT) // Read measured generator voltage value (VOUT)
if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_TSUP_VOLTAGE_MEAS, buf, 2) < 0) if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_TSUP_VOLTAGE_MEAS, buf, 2) < 0)
@ -2373,8 +2423,7 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp) {
else { else {
if (analog_raw_data & 0x0800) if (analog_raw_data & 0x0800)
analog_raw_data |= 0xF000; analog_raw_data |= 0xF000;
fmsg_out(fp, "%sVout measured %s: %.02f V\n", p, fmsg_out(fp, "%sVout measured : %.02f V\n", p, (float) analog_raw_data / -200.0);
verbose? "": " ", ((float) analog_raw_data / -200.0));
} }
// Read channel A voltage // Read channel A voltage
@ -2386,8 +2435,7 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp) {
else { else {
if (analog_raw_data & 0x0800) if (analog_raw_data & 0x0800)
analog_raw_data |= 0xF000; analog_raw_data |= 0xF000;
fmsg_out(fp, "%sCh A voltage %s: %.03f V\n", p, fmsg_out(fp, "%sCh A voltage : %.03f V\n", p, (float) analog_raw_data / -200.0);
verbose? "": " ", ((float) analog_raw_data / -200.0));
} }
// Read channel A current // Read channel A current
@ -2397,8 +2445,7 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp) {
if (buf[0] != 0x90) if (buf[0] != 0x90)
pmsg_error("invalid PARM3_ANALOG_A_CURRENT data packet format\n"); pmsg_error("invalid PARM3_ANALOG_A_CURRENT data packet format\n");
else else
fmsg_out(fp, "%sCh A current %s: %.3f mA\n", p, fmsg_out(fp, "%sCh A current : %.3f mA\n", p, (float) analog_raw_data * 0.003472);
verbose? "": " ", (float) analog_raw_data * 0.003472);
// Read channel B voltage // Read channel B voltage
if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_ANALOG_B_VOLTAGE, buf, 2) < 0) if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_ANALOG_B_VOLTAGE, buf, 2) < 0)
@ -2409,8 +2456,7 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp) {
else { else {
if (analog_raw_data & 0x0800) if (analog_raw_data & 0x0800)
analog_raw_data |= 0xF000; analog_raw_data |= 0xF000;
fmsg_out(fp, "%sCh B voltage %s: %.03f V\n", p, fmsg_out(fp, "%sCh B voltage : %.03f V\n", p, (float) analog_raw_data / -200.0);
verbose? "": " ", (float) analog_raw_data / -200.0);
} }
// Read channel B current // Read channel B current
@ -2422,8 +2468,7 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp) {
else { else {
if (analog_raw_data & 0x0800) if (analog_raw_data & 0x0800)
analog_raw_data |= 0xF000; analog_raw_data |= 0xF000;
fmsg_out(fp, "%sCh B current %s: %.3f mA\n", p, fmsg_out(fp, "%sCh B current : %.3f mA\n", p, (float) analog_raw_data * 0.555556);
verbose? "": " ", (float) analog_raw_data * 0.555556);
} }
break; break;
} }
@ -2431,34 +2476,37 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp) {
// Print clocks if programmer typ is not TPI // Print clocks if programmer typ is not TPI
if (strcmp(pgm->type, "JTAGICE3_TPI")) { if (strcmp(pgm->type, "JTAGICE3_TPI")) {
// Get current programming mode and target type from to determine what data to print
if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CONNECTION, prog_mode, 1) < 0)
return;
if (jtag3_getparm(pgm, SCOPE_AVR, 0, PARM3_ARCH, &prog_mode[1], 1) < 0)
return;
if (prog_mode[0] == PARM3_CONN_JTAG) {
if (prog_mode[1] == PARM3_ARCH_XMEGA) {
if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_XMEGA_JTAG, buf, 2) < 0)
return;
if (b2_to_u16(buf) > 0)
fmsg_out(fp, "%sJTAG clk Xmega : %u kHz\n", p, b2_to_u16(buf));
} else {
if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_MEGA_PROG, buf, 2) < 0) if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_MEGA_PROG, buf, 2) < 0)
return; return;
if (b2_to_u16(buf) > 0)
if (b2_to_u16(buf) > 0) { fmsg_out(fp, "%sJTAG clk prog. : %u kHz\n", p, b2_to_u16(buf));
fmsg_out(fp, "%sJTAG clock megaAVR/program : %u kHz\n", p, b2_to_u16(buf));
}
if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_MEGA_DEBUG, buf, 2) < 0) if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_MEGA_DEBUG, buf, 2) < 0)
return; return;
if (b2_to_u16(buf) > 0)
if (b2_to_u16(buf) > 0) { fmsg_out(fp, "%sJTAG clk debug : %u kHz\n", p, b2_to_u16(buf));
fmsg_out(fp, "%sJTAG clock megaAVR/debug : %u kHz\n", p, b2_to_u16(buf));
} }
if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_XMEGA_JTAG, buf, 2) < 0)
return;
if (b2_to_u16(buf) > 0) {
fmsg_out(fp, "%sJTAG clock Xmega : %u kHz\n", p, b2_to_u16(buf));
} }
else if (prog_mode[0] == PARM3_CONN_PDI || prog_mode[0] == PARM3_CONN_UPDI) {
if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_XMEGA_PDI, buf, 2) < 0) if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_XMEGA_PDI, buf, 2) < 0)
return; return;
if (b2_to_u16(buf) > 0)
if (b2_to_u16(buf) > 0) { fmsg_out(fp, "%sPDI/UPDI clk : %u kHz\n", p, b2_to_u16(buf));
fmsg_out(fp, "%sPDI/UPDI clock Xmega/megaAVR : %u kHz\n", p, b2_to_u16(buf));
} }
} }
fmsg_out(fp, "\n");
} }
static void jtag3_print_parms(const PROGRAMMER *pgm, FILE *fp) { static void jtag3_print_parms(const PROGRAMMER *pgm, FILE *fp) {
@ -2535,6 +2583,11 @@ static int jtag3_send_tpi(const PROGRAMMER *pgm, unsigned char *data, size_t len
} }
cmdbuf[0] = SCOPE_AVR_TPI; cmdbuf[0] = SCOPE_AVR_TPI;
if (len > INT_MAX) {
pmsg_error("invalid jtag3_send_tpi() packet length %zu\n", len);
free(cmdbuf);
return -1;
}
memcpy(cmdbuf + 1, data, len); memcpy(cmdbuf + 1, data, len);
msg_trace("[TPI send] "); msg_trace("[TPI send] ");
@ -2561,7 +2614,7 @@ int jtag3_recv_tpi(const PROGRAMMER *pgm, unsigned char **msg) {
memcpy(*msg, *msg + 1, rv); memcpy(*msg, *msg + 1, rv);
msg_trace("[TPI recv] "); msg_trace("[TPI recv] ");
for (size_t i=0; i<rv; i++) for (int i=0; i<rv; i++)
msg_trace("0x%02x ", (*msg)[i]); msg_trace("0x%02x ", (*msg)[i]);
msg_trace("\n"); msg_trace("\n");
@ -2626,7 +2679,7 @@ static int jtag3_initialize_tpi(const PROGRAMMER *pgm, const AVRPART *p) {
return -1; return -1;
free(resp); free(resp);
jtag3_print_parms(pgm, stderr); jtag3_print_parms1(pgm, progbuf, stderr);
return 0; return 0;
} }
@ -2804,7 +2857,7 @@ static int jtag3_paged_load_tpi(const PROGRAMMER *pgm, const AVRPART *p,
cmd[0] = XPRG_CMD_READ_MEM; cmd[0] = XPRG_CMD_READ_MEM;
cmd[1] = tpi_get_memtype(m); cmd[1] = tpi_get_memtype(m);
if(m->blocksize > page_size) if(m->blocksize > (int) page_size)
page_size = m->blocksize; page_size = m->blocksize;
serial_recv_timeout = 100; serial_recv_timeout = 100;
@ -2822,13 +2875,19 @@ static int jtag3_paged_load_tpi(const PROGRAMMER *pgm, const AVRPART *p,
if ((status = jtag3_command_tpi(pgm, cmd, 8, &resp, "Read Memory")) < 0) if ((status = jtag3_command_tpi(pgm, cmd, 8, &resp, "Read Memory")) < 0)
return -1; return -1;
if (resp[1] != XPRG_ERR_OK || if (resp[1] != XPRG_ERR_OK || status < (int) block_size + 2) {
status < block_size + 2) {
pmsg_error("wrong/short reply to read memory command\n"); pmsg_error("wrong/short reply to read memory command\n");
serial_recv_timeout = otimeout; serial_recv_timeout = otimeout;
free(resp); free(resp);
return -1; return -1;
} }
if (status < 2) {
pmsg_error("unexpected return value %d from jtag3_paged_load_tpi()\n", status);
free(resp);
return -1;
}
memcpy(m->buf + addr, resp + 2, status - 2); memcpy(m->buf + addr, resp + 2, status - 2);
free(resp); free(resp);
} }

View File

@ -38,6 +38,7 @@ int jtag3_setparm(const PROGRAMMER *pgm, unsigned char scope,
unsigned char *value, unsigned char length); unsigned char *value, unsigned char length);
int jtag3_command(const PROGRAMMER *pgm, unsigned char *cmd, unsigned int cmdlen, int jtag3_command(const PROGRAMMER *pgm, unsigned char *cmd, unsigned int cmdlen,
unsigned char **resp, const char *descr); unsigned char **resp, const char *descr);
void jtag3_display(const PROGRAMMER *pgm, const char *p);
void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp); void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp);
int jtag3_set_vtarget(const PROGRAMMER *pgm, double voltage); int jtag3_set_vtarget(const PROGRAMMER *pgm, double voltage);
extern const char jtag3_desc[]; extern const char jtag3_desc[];

View File

@ -649,6 +649,7 @@ union pinfo
struct serial_device { struct serial_device {
// open should return -1 on error, other values on success // open should return -1 on error, other values on success
int (*open)(const char *port, union pinfo pinfo, union filedescriptor *fd); int (*open)(const char *port, union pinfo pinfo, union filedescriptor *fd);
const char *(*serno)();
int (*setparams)(const union filedescriptor *fd, long baud, unsigned long cflags); int (*setparams)(const union filedescriptor *fd, long baud, unsigned long cflags);
void (*close)(union filedescriptor *fd); void (*close)(union filedescriptor *fd);
@ -671,6 +672,7 @@ extern struct serial_device avrdoper_serdev;
extern struct serial_device usbhid_serdev; extern struct serial_device usbhid_serdev;
#define serial_open (serdev->open) #define serial_open (serdev->open)
#define serial_serno (serdev->serno)
#define serial_setparams (serdev->setparams) #define serial_setparams (serdev->setparams)
#define serial_close (serdev->close) #define serial_close (serdev->close)
#define serial_send (serdev->send) #define serial_send (serdev->send)

View File

@ -852,6 +852,7 @@ retry:
case STATUS_SET_PARAM_MISSING: case STATUS_SET_PARAM_MISSING:
msg = "The `Set Device Parameters' have not been " msg = "The `Set Device Parameters' have not been "
"executed in advance of this command"; "executed in advance of this command";
break;
default: default:
sprintf(msgbuf, "unknown, code 0x%02x", buf[1]); sprintf(msgbuf, "unknown, code 0x%02x", buf[1]);
@ -1577,6 +1578,9 @@ static int stk500v2_open(PROGRAMMER *pgm, const char *port) {
return -1; return -1;
} }
// Get USB serial number
pgm->usbsn = serial_serno();
/* /*
* drain any extraneous input * drain any extraneous input
*/ */
@ -3043,6 +3047,8 @@ static void stk500v2_display(const PROGRAMMER *pgm, const char *p) {
stk500v2_getparm(pgm, PARAM_SW_MAJOR, &maj); stk500v2_getparm(pgm, PARAM_SW_MAJOR, &maj);
stk500v2_getparm(pgm, PARAM_SW_MINOR, &min); stk500v2_getparm(pgm, PARAM_SW_MINOR, &min);
msg_info("%sHardware Version: %d\n", p, hdw); msg_info("%sHardware Version: %d\n", p, hdw);
if (pgm->usbsn && *pgm->usbsn)
msg_info("%sSerial number : %s\n", p, pgm->usbsn);
msg_info("%sFirmware Version Controller : %d.%02d\n", p, maj, min); msg_info("%sFirmware Version Controller : %d.%02d\n", p, maj, min);
if (PDATA(pgm)->pgmtype == PGMTYPE_STK600) { if (PDATA(pgm)->pgmtype == PGMTYPE_STK600) {
stk500v2_getparm(pgm, PARAM_SW_MAJOR_PERIPHERY1, &maj_s1); stk500v2_getparm(pgm, PARAM_SW_MAJOR_PERIPHERY1, &maj_s1);
@ -3081,6 +3087,12 @@ static void stk500v2_display(const PROGRAMMER *pgm, const char *p) {
msg_info("%sRC_ID table rev : %d\n", p, rev); msg_info("%sRC_ID table rev : %d\n", p, rev);
stk500v2_getparm2(pgm, PARAM2_EC_ID_TABLE_REV, &rev); stk500v2_getparm2(pgm, PARAM2_EC_ID_TABLE_REV, &rev);
msg_info("%sEC_ID table rev : %d\n", p, rev); msg_info("%sEC_ID table rev : %d\n", p, rev);
} else if (PDATA(pgm)->pgmtype == PGMTYPE_JTAGICE3) {
PROGRAMMER *pgmcp = pgm_dup(pgm);
pgmcp->cookie = PDATA(pgm)->chained_pdata;
jtag3_display(pgmcp, p);
msg_info("\n");
pgm_free(pgmcp);
} }
stk500v2_print_parms1(pgm, p, stderr); stk500v2_print_parms1(pgm, p, stderr);
@ -3118,16 +3130,7 @@ static void stk500v2_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp
jtagmkII_getparm(pgmcp, PAR_OCD_VTARGET, vtarget_jtag); jtagmkII_getparm(pgmcp, PAR_OCD_VTARGET, vtarget_jtag);
pgm_free(pgmcp); pgm_free(pgmcp);
fmsg_out(fp, "%sVtarget : %.1f V\n", p, b2_to_u16(vtarget_jtag) / 1000.0); fmsg_out(fp, "%sVtarget : %.1f V\n", p, b2_to_u16(vtarget_jtag) / 1000.0);
} else if (PDATA(pgm)->pgmtype == PGMTYPE_JTAGICE3) { } else if (PDATA(pgm)->pgmtype != PGMTYPE_JTAGICE3) {
PROGRAMMER *pgmcp = pgm_dup(pgm);
pgmcp->cookie = PDATA(pgm)->chained_pdata;
pgmcp->id = lcreat(NULL, 0);
// Copy pgm->id contents over to pgmcp->id
for(LNODEID ln=lfirst(pgm->id); ln; ln=lnext(ln))
ladd(pgmcp->id, cfg_strdup("stk500v2_print_parms1()", ldata(ln)));
jtag3_print_parms1(pgmcp, p, fp);
pgm_free(pgmcp);
} else {
stk500v2_getparm(pgm, PARAM_VTARGET, &vtarget); stk500v2_getparm(pgm, PARAM_VTARGET, &vtarget);
fmsg_out(fp, "%sVtarget : %.1f V\n", p, vtarget / 10.0); fmsg_out(fp, "%sVtarget : %.1f V\n", p, vtarget / 10.0);
} }
@ -3173,14 +3176,19 @@ static void stk500v2_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp
case PGMTYPE_JTAGICE3: case PGMTYPE_JTAGICE3:
{ {
unsigned char cmd[4]; unsigned char cmd[4];
cmd[0] = CMD_GET_SCK; cmd[0] = CMD_GET_SCK;
if (stk500v2_jtag3_send(pgm, cmd, 1) >= 0 && if (stk500v2_jtag3_send(pgm, cmd, 1) >= 0 && stk500v2_jtag3_recv(pgm, cmd, 4) >= 2) {
stk500v2_jtag3_recv(pgm, cmd, 4) >= 2) {
unsigned int sck = cmd[1] | (cmd[2] << 8); unsigned int sck = cmd[1] | (cmd[2] << 8);
fmsg_out(fp, "%sSCK period : %.2f us\n", p, fmsg_out(fp, "%sSCK period : %.2f us\n", p, (1E6 / (1000.0 * sck)));
(float)(1E6 / (1000.0 * sck)));
} }
PROGRAMMER *pgmcp = pgm_dup(pgm);
pgmcp->cookie = PDATA(pgm)->chained_pdata;
pgmcp->id = lcreat(NULL, 0);
// Copy pgm->id contents over to pgmcp->id
for(LNODEID ln=lfirst(pgm->id); ln; ln=lnext(ln))
ladd(pgmcp->id, cfg_strdup("stk500v2_print_parms1()", ldata(ln)));
jtag3_print_parms1(pgmcp, p, fp);
pgm_free(pgmcp);
} }
break; break;

View File

@ -42,6 +42,12 @@
#include "usbdevs.h" #include "usbdevs.h"
static const char *usbsn = "";
const char *usbhid_get_serno() {
return usbsn;
}
/* /*
* The "baud" parameter is meaningless for USB devices, so we reuse it * The "baud" parameter is meaningless for USB devices, so we reuse it
* to pass the desired USB device ID. * to pass the desired USB device ID.
@ -120,7 +126,6 @@ static int usbhid_open(const char *port, union pinfo pinfo, union filedescriptor
return -1; return -1;
} }
} else { } else {
/* No serial number requested, pass straight to hid_open() */
dev = hid_open(pinfo.usbinfo.vid, pinfo.usbinfo.pid, NULL); dev = hid_open(pinfo.usbinfo.vid, pinfo.usbinfo.pid, NULL);
if (dev == NULL) if (dev == NULL)
{ {
@ -130,6 +135,18 @@ static int usbhid_open(const char *port, union pinfo pinfo, union filedescriptor
} }
} }
// Store USB serial number to usbsn string
wchar_t sn[256];
if (hid_get_serial_number_string(dev, sn, sizeof(sn)/sizeof(*sn)) == 0) {
size_t n = wcstombs(NULL, sn, 0) + 1;
if (n) {
char *cn = cfg_malloc(__func__, n);
if (wcstombs(cn, sn, n) != (size_t) -1)
usbsn = cache_string(cn);
free(cn);
}
}
fd->usb.handle = dev; fd->usb.handle = dev;
/* /*
@ -302,6 +319,7 @@ static int usbhid_drain(const union filedescriptor *fd, int display) {
*/ */
struct serial_device usbhid_serdev = { struct serial_device usbhid_serdev = {
.open = usbhid_open, .open = usbhid_open,
.serno = usbhid_get_serno,
.close = usbhid_close, .close = usbhid_close,
.send = usbhid_send, .send = usbhid_send,
.recv = usbhid_recv, .recv = usbhid_recv,

View File

@ -58,6 +58,12 @@ static int buflen = -1, bufptr;
static int usb_interface; static int usb_interface;
static const char *usbsn = "";
const char *usbdev_get_serno() {
return usbsn;
}
/* /*
* The "baud" parameter is meaningless for USB devices, so we reuse it * The "baud" parameter is meaningless for USB devices, so we reuse it
* to pass the desired USB device ID. * to pass the desired USB device ID.
@ -138,7 +144,7 @@ static int usbdev_open(const char *port, union pinfo pinfo, union filedescriptor
else else
strcpy(string, "[unknown]"); strcpy(string, "[unknown]");
} }
usbsn = cache_string(string);
if (usb_get_string_simple(udev, if (usb_get_string_simple(udev,
dev->descriptor.iProduct, dev->descriptor.iProduct,
product, sizeof(product)) < 0) product, sizeof(product)) < 0)
@ -334,7 +340,7 @@ static int usbdev_send(const union filedescriptor *fd, const unsigned char *bp,
* 0. * 0.
*/ */
do { do {
tx_size = (mlen < fd->usb.max_xfer)? mlen: fd->usb.max_xfer; tx_size = ((int) mlen < fd->usb.max_xfer)? (int) mlen: fd->usb.max_xfer;
if (fd->usb.use_interrupt_xfer) if (fd->usb.use_interrupt_xfer)
rv = usb_interrupt_write(udev, fd->usb.wep, (char *)bp, tx_size, 10000); rv = usb_interrupt_write(udev, fd->usb.wep, (char *)bp, tx_size, 10000);
else else
@ -416,7 +422,7 @@ static int usbdev_recv(const union filedescriptor *fd, unsigned char *buf, size_
if (usb_fill_buf(udev, fd->usb.max_xfer, fd->usb.rep, fd->usb.use_interrupt_xfer) < 0) if (usb_fill_buf(udev, fd->usb.max_xfer, fd->usb.rep, fd->usb.use_interrupt_xfer) < 0)
return -1; return -1;
} }
amnt = buflen - bufptr > nbytes? nbytes: buflen - bufptr; amnt = buflen - bufptr > (int) nbytes? (int) nbytes: buflen - bufptr;
memcpy(buf + i, usbbuf + bufptr, amnt); memcpy(buf + i, usbbuf + bufptr, amnt);
bufptr += amnt; bufptr += amnt;
nbytes -= amnt; nbytes -= amnt;
@ -500,7 +506,7 @@ static int usbdev_recv_frame(const union filedescriptor *fd, unsigned char *buf,
return -1; return -1;
} }
if (rv <= nbytes) if (rv <= (int) nbytes)
{ {
memcpy (buf, usbbuf, rv); memcpy (buf, usbbuf, rv);
buf += rv; buf += rv;
@ -576,6 +582,7 @@ static int usbdev_drain(const union filedescriptor *fd, int display)
struct serial_device usb_serdev = struct serial_device usb_serdev =
{ {
.open = usbdev_open, .open = usbdev_open,
.serno = usbdev_get_serno,
.close = usbdev_close, .close = usbdev_close,
.send = usbdev_send, .send = usbdev_send,
.recv = usbdev_recv, .recv = usbdev_recv,
@ -589,6 +596,7 @@ struct serial_device usb_serdev =
struct serial_device usb_serdev_frame = struct serial_device usb_serdev_frame =
{ {
.open = usbdev_open, .open = usbdev_open,
.serno = usbdev_get_serno,
.close = usbdev_close, .close = usbdev_close,
.send = usbdev_send, .send = usbdev_send,
.recv = usbdev_recv_frame, .recv = usbdev_recv_frame,