From e39133daf511c3eabb04a6e41567cd54cfafa822 Mon Sep 17 00:00:00 2001 From: MCUdude Date: Wed, 28 Sep 2022 21:59:50 +0200 Subject: [PATCH] Initial support for Power Debugger analog reading Voltage and current though channel A and B --- src/jtag3.c | 102 +++++++++++++++++++++++++++++++++++++++----- src/jtag3.h | 2 + src/jtag3_private.h | 28 +++++++----- src/stk500v2.c | 10 ++--- src/term.c | 2 +- 5 files changed, 117 insertions(+), 27 deletions(-) diff --git a/src/jtag3.c b/src/jtag3.c index 04bd1e83..175e0e47 100644 --- a/src/jtag3.c +++ b/src/jtag3.c @@ -103,7 +103,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, unsigned long addr, unsigned char data); static int jtag3_set_sck_period(const PROGRAMMER *pgm, double v); -static void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p); +void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p); static int jtag3_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m, unsigned int page_size, unsigned int addr, unsigned int n_bytes); @@ -2339,7 +2339,7 @@ int jtag3_read_sib(const PROGRAMMER *pgm, const AVRPART *p, char *sib) { return 0; } -static int jtag3_set_vtarget(const PROGRAMMER *pgm, double v) { +int jtag3_set_vtarget(const PROGRAMMER *pgm, double v) { unsigned uaref, utarg; unsigned char buf[2]; @@ -2407,15 +2407,89 @@ static void jtag3_display(const PROGRAMMER *pgm, const char *p) { } -static void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p) { - unsigned char buf[2]; +void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p) { + unsigned char buf[3]; if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_VTARGET, buf, 2) < 0) return; - avrdude_message(MSG_INFO, "%sVtarget %s: %.2f V\n", p, verbose ? "" : " ", b2_to_u16(buf) / 1000.0); + // Print features unique to the Power Debugger + //if (strncmp("powerdebugger", ldata(lfirst(pgm->id)), strlen("powerdebugger")) == 0) + if (*(int *)(ldata(lfirst(pgm->usbpid))) == 0x2144){ + short analog_raw_data; + + // Read generator set voltage value (VOUT) + if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_VADJUST, buf, 2) < 0) + return; + analog_raw_data = b2_to_u16(buf); + avrdude_message(MSG_INFO, "%sVout set %s: %.2f V\n", p, + verbose ? "" : " ", analog_raw_data / 1000.0); + + // Read measured generator voltage value (VOUT) + if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_TSUP_VOLTAGE_MEAS, buf, 2) < 0) + return; + analog_raw_data = ((buf[0] & 0x0F) << 8) + buf[1]; + if ((buf[0] & 0xF0) != 0x30) + avrdude_message(MSG_INFO, "%s: jtag3_print_parms1(): invalid PARM3_TSUP_VOLTAGE_MEAS data packet format\n", progname); + else { + if (analog_raw_data & 0x0800) + analog_raw_data |= 0xF000; + avrdude_message(MSG_INFO, "%sVout measured %s: %.02f V\n", p, + verbose ? "" : " ", ((float)analog_raw_data / -200.0)); + } + + // Read channel A voltage + if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_ANALOG_A_VOLTAGE, buf, 2) < 0) + return; + analog_raw_data = ((buf[0] & 0x0F) << 8) + buf[1]; + if ((buf[0] & 0xF0) != 0x20) + avrdude_message(MSG_INFO, "%s: jtag3_print_parms1(): invalid PARM3_ANALOG_A_VOLTAGE data packet format\n", progname); + else { + if (analog_raw_data & 0x0800) + analog_raw_data |= 0xF000; + avrdude_message(MSG_INFO, "%sCh A voltage %s: %.03f V\n", p, + verbose ? "" : " ", ((float)analog_raw_data / -200.0)); + } + + // Read channel A current + if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_ANALOG_A_CURRENT, buf, 3) < 0) + return; + analog_raw_data = (buf[1] << 8) + buf[2]; + if (buf[0] != 0x90) + avrdude_message(MSG_INFO, "%s: jtag3_print_parms1(): invalid PARM3_ANALOG_A_CURRENT data packet format\n", progname); + else + avrdude_message(MSG_INFO, "%sCh A current %s: %.3f mA\n", p, + verbose ? "" : " ", ((float)analog_raw_data * 0.003472)); + + // Read channel B voltage + if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_ANALOG_B_VOLTAGE, buf, 2) < 0) + return; + analog_raw_data = ((buf[0] & 0x0F) << 8) + buf[1]; + if ((buf[0] & 0xF0) != 0x10) + avrdude_message(MSG_INFO, "%s: jtag3_print_parms1(): invalid PARM3_ANALOG_B_VOLTAGE data packet format\n", progname); + else { + if (analog_raw_data & 0x0800) + analog_raw_data |= 0xF000; + avrdude_message(MSG_INFO, "%sCh B voltage %s: %.03f V\n", p, + verbose ? "" : " ", ((float)analog_raw_data / -200.0)); + } + + // Read channel B current + if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_ANALOG_B_CURRENT, buf, 3) < 0) + return; + analog_raw_data = ((buf[0] & 0x0F) << 8) + buf[1]; + if ((buf[0] & 0xF0) != 0x00) + avrdude_message(MSG_INFO, "%s: jtag3_print_parms1(): invalid PARM3_ANALOG_B_CURRENT data packet format\n", progname); + else { + if (analog_raw_data & 0x0800) + analog_raw_data |= 0xF000; + avrdude_message(MSG_INFO, "%sCh B current %s: %.3f mA\n", p, + verbose ? "" : " ", ((float)analog_raw_data * 0.555556)); + } + } + if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_MEGA_PROG, buf, 2) < 0) return; @@ -2444,7 +2518,7 @@ static void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p) { return; if (b2_to_u16(buf) > 0) { - avrdude_message(MSG_INFO, "%sPDI/UPDI clock Xmega/megaAVR : %u kHz\n\n", p, + avrdude_message(MSG_INFO, "%sPDI/UPDI clock Xmega/megaAVR : %u kHz\n", p, b2_to_u16(buf)); } } @@ -2525,6 +2599,9 @@ void jtag3_initpgm(PROGRAMMER *pgm) { pgm->teardown = jtag3_teardown; pgm->page_size = 256; pgm->flag = PGM_FL_IS_JTAG; + + if (matches(ldata(lfirst(pgm->id)), "powerdebugger")) + pgm->set_vtarget = jtag3_set_vtarget; } const char jtag3_dw_desc[] = "Atmel JTAGICE3 in debugWire mode"; @@ -2556,6 +2633,9 @@ void jtag3_dw_initpgm(PROGRAMMER *pgm) { pgm->teardown = jtag3_teardown; pgm->page_size = 256; pgm->flag = PGM_FL_IS_DW; + + if (matches(ldata(lfirst(pgm->id)), "powerdebugger_dw")) + pgm->set_vtarget = jtag3_set_vtarget; } const char jtag3_pdi_desc[] = "Atmel JTAGICE3 in PDI mode"; @@ -2589,6 +2669,9 @@ void jtag3_pdi_initpgm(PROGRAMMER *pgm) { pgm->teardown = jtag3_teardown; pgm->page_size = 256; pgm->flag = PGM_FL_IS_PDI; + + if (matches(ldata(lfirst(pgm->id)), "powerdebugger_pdi")) + pgm->set_vtarget = jtag3_set_vtarget; } const char jtag3_updi_desc[] = "Atmel JTAGICE3 in UPDI mode"; @@ -2626,11 +2709,8 @@ void jtag3_updi_initpgm(PROGRAMMER *pgm) { pgm->unlock = jtag3_unlock_erase_key; pgm->read_sib = jtag3_read_sib; - /* - * enable target voltage adjustment for PKOB/nEDBG boards - */ - if (matches(ldata(lfirst(pgm->id)), "pkobn_updi")) { + if (matches(ldata(lfirst(pgm->id)), "pkobn_updi") || + matches(ldata(lfirst(pgm->id)), "powerdebugger_updi")) pgm->set_vtarget = jtag3_set_vtarget; - } } diff --git a/src/jtag3.h b/src/jtag3.h index c871c019..945ddcb2 100644 --- a/src/jtag3.h +++ b/src/jtag3.h @@ -38,6 +38,8 @@ int jtag3_setparm(const PROGRAMMER *pgm, unsigned char scope, unsigned char *value, unsigned char length); int jtag3_command(const PROGRAMMER *pgm, unsigned char *cmd, unsigned int cmdlen, unsigned char **resp, const char *descr); +void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p); +int jtag3_set_vtarget(const PROGRAMMER *pgm, double voltage); extern const char jtag3_desc[]; extern const char jtag3_dw_desc[]; extern const char jtag3_pdi_desc[]; diff --git a/src/jtag3_private.h b/src/jtag3_private.h index ddc7e2e3..2e414c71 100644 --- a/src/jtag3_private.h +++ b/src/jtag3_private.h @@ -184,16 +184,24 @@ * precedes each parameter address. There are distinct parameter * sets for generic and AVR scope. */ -#define PARM3_HW_VER 0x00 /* section 0, generic scope, 1 byte */ -#define PARM3_FW_MAJOR 0x01 /* section 0, generic scope, 1 byte */ -#define PARM3_FW_MINOR 0x02 /* section 0, generic scope, 1 byte */ -#define PARM3_FW_RELEASE 0x03 /* section 0, generic scope, 1 byte; - * always asked for by Atmel Studio, - * but never displayed there */ -#define PARM3_VTARGET 0x00 /* section 1, generic scope, 2 bytes, in millivolts */ -#define PARM3_VBUF 0x01 /* section 1, generic scope, 2 bytes, bufferred target voltage reference */ -#define PARM3_VUSB 0x02 /* section 1, generic scope, 2 bytes, USB voltage */ -#define PARM3_VADJUST 0x20 /* section 1, generic scope, 2 bytes, set voltage */ +#define PARM3_HW_VER 0x00 /* section 0, generic scope, 1 byte */ +#define PARM3_FW_MAJOR 0x01 /* section 0, generic scope, 1 byte */ +#define PARM3_FW_MINOR 0x02 /* section 0, generic scope, 1 byte */ +#define PARM3_FW_RELEASE 0x03 /* section 0, generic scope, 1 byte; + * always asked for by Atmel Studio, + * but never displayed there */ + +#define PARM3_VTARGET 0x00 /* section 1, generic scope, 2 bytes, in millivolts */ +#define PARM3_VBUF 0x01 /* section 1, generic scope, 2 bytes, bufferred target voltage reference */ +#define PARM3_VUSB 0x02 /* section 1, generic scope, 2 bytes, USB voltage */ +#define PARM3_ANALOG_A_CURRENT 0x10 /* section 1, generic scope, 2 bytes, Ch A current in milliamps, Powerdebugger only */ +#define PARM3_ANALOG_A_VOLTAGE 0x11 /* section 1, generic scope, 2 bytes, Ch A voltage in millivolts, Powerdebugger only */ +#define PARM3_ANALOG_B_CURRENT 0x12 /* section 1, generic scope, 2 bytes, Ch B current in milliamps, Powerdebugger only */ +#define PARM3_ANALOG_B_VOLTAGE 0x13 /* section 1, generic scope, 2 bytes, Ch V voltage in millivolts, Powerdebugger only */ +#define PARM3_TSUP_VOLTAGE_MEAS 0x14 /* section 1, generic scope, 2 bytes, target voltage measurement in millivolts */ +#define PARM3_USB_VOLTAGE_MEAS 0x15 /* section 1, generic scope, 2 bytes, USB voltage measurement in millivolts */ +#define PARM3_VADJUST 0x20 /* section 1, generic scope, 2 bytes, set voltage in millivolts */ +#define PARM3_ANALOG_STATUS 0x30 /* section 1, generic scope, 2 bytes, analog status */ #define PARM3_DEVICEDESC 0x00 /* section 2, memory etc. configuration, * 31 bytes for tiny/mega AVR, 47 bytes diff --git a/src/stk500v2.c b/src/stk500v2.c index a7477030..09f4a4ca 100644 --- a/src/stk500v2.c +++ b/src/stk500v2.c @@ -3226,11 +3226,8 @@ static void stk500v2_print_parms1(const PROGRAMMER *pgm, const char *p) { } else if (PDATA(pgm)->pgmtype == PGMTYPE_JTAGICE3) { PROGRAMMER *pgmcp = pgm_dup(pgm); pgmcp->cookie = PDATA(pgm)->chained_pdata; - jtag3_getparm(pgmcp, SCOPE_GENERAL, 1, PARM3_VTARGET, vtarget_jtag, 2); + jtag3_print_parms1(pgmcp, p); pgm_free(pgmcp); - avrdude_message(MSG_INFO, "%sVtarget : %.1f V\n", p, - b2_to_u16(vtarget_jtag) / 1000.0); - } else { stk500v2_getparm(pgm, PARAM_VTARGET, &vtarget); avrdude_message(MSG_INFO, "%sVtarget : %.1f V\n", p, vtarget / 10.0); @@ -3282,7 +3279,7 @@ static void stk500v2_print_parms1(const PROGRAMMER *pgm, const char *p) { if (stk500v2_jtag3_send(pgm, cmd, 1) >= 0 && stk500v2_jtag3_recv(pgm, cmd, 4) >= 2) { unsigned int sck = cmd[1] | (cmd[2] << 8); - avrdude_message(MSG_INFO, "%sSCK period : %.2f us\n", p, + avrdude_message(MSG_INFO, "%sSCK period : %.2f us\n", p, (float)(1E6 / (1000.0 * sck))); } } @@ -4681,4 +4678,7 @@ void stk500v2_jtag3_initpgm(PROGRAMMER *pgm) { pgm->setup = stk500v2_jtag3_setup; pgm->teardown = stk500v2_jtag3_teardown; pgm->page_size = 256; + + if (strcmp(ldata(lfirst(pgm->id)), "powerdebugger_isp") == 0) + pgm->set_vtarget = jtag3_set_vtarget; } diff --git a/src/term.c b/src/term.c index 512e5a3c..46e8d52a 100644 --- a/src/term.c +++ b/src/term.c @@ -854,7 +854,7 @@ static int cmd_parms(PROGRAMMER * pgm, struct avrpart * p, return -1; } pgm->print_parms(pgm); - + terminal_message(MSG_INFO, "\n"); return 0; }