From 10ccf0f515f17575f8607d02a9ed148e3b074176 Mon Sep 17 00:00:00 2001 From: Jan Egil Ruud Date: Mon, 21 Nov 2022 21:18:13 +0100 Subject: [PATCH 01/22] Initial commit for jtag3 TPI support. Can read signature on ATtiny104 XPlained mini, but nothing else yet. --- src/avrdude.conf.in | 13 +++ src/jtag3.c | 212 +++++++++++++++++++++++++++++++++++++++++ src/jtag3.h | 2 + src/jtag3_private.h | 52 ++++++++++ src/pgm_type.c | 1 + src/stk500v2.c | 8 +- src/stk500v2_private.h | 45 --------- 7 files changed, 284 insertions(+), 49 deletions(-) diff --git a/src/avrdude.conf.in b/src/avrdude.conf.in index 0a6f71d7..af51d3dc 100644 --- a/src/avrdude.conf.in +++ b/src/avrdude.conf.in @@ -2098,6 +2098,19 @@ programmer hvupdi_support = 1; ; +#------------------------------------------------------------ +# xplainedmini_tpi +#------------------------------------------------------------ + +programmer + id = "xplainedmini_tpi"; + desc = "Atmel AVR XplainedMini in TPI mode"; + type = "jtagice3_tpi"; + prog_modes = PM_TPI; + connection_type = usb; + usbpid = 0x2145; +; + #------------------------------------------------------------ # atmelice #------------------------------------------------------------ diff --git a/src/jtag3.c b/src/jtag3.c index 146bed4b..de23a407 100644 --- a/src/jtag3.c +++ b/src/jtag3.c @@ -89,6 +89,7 @@ struct pdata #define PGM_FL_IS_JTAG (0x0004) #define PGM_FL_IS_EDBG (0x0008) #define PGM_FL_IS_UPDI (0x0010) +#define PGM_FL_IS_TPI (0x0020) static int jtag3_open(PROGRAMMER *pgm, const char *port); static int jtag3_edbg_prepare(const PROGRAMMER *pgm); @@ -2513,6 +2514,187 @@ static unsigned int jtag3_memaddr(const PROGRAMMER *pgm, const AVRPART *p, const return addr; } +/* + * Send the data as a JTAGICE3 encapsulated TPI packet. + */ +static int jtag3_send_tpi(const PROGRAMMER *pgm, unsigned char *data, size_t len) { + unsigned char *cmdbuf; + int rv; + + if ((cmdbuf = malloc(len + 1)) == NULL) { + pmsg_error("out of memory for command packet\n"); + exit(1); + } + + cmdbuf[0] = SCOPE_AVR_TPI; + memcpy(cmdbuf + 1, data, len); + + msg_trace("STK500V2: jtag3_send_tpi("); + for (size_t i=0; idesc, addr); + + + buf[0] = XPRG_CMD_READ_MEM; + + if (strcmp(mem->desc, "lfuse") == 0 || + strcmp(mem->desc, "fuse") == 0) { + buf[1] = XPRG_MEM_TYPE_FUSE; + addr = 0; + } else if (strcmp(mem->desc, "hfuse") == 0) { + buf[1] = XPRG_MEM_TYPE_FUSE; + addr = 1; + } else if (strcmp(mem->desc, "efuse") == 0) { + buf[1] = XPRG_MEM_TYPE_FUSE; + addr = 2; + } else if (strcmp(mem->desc, "lock") == 0) { + buf[1] = XPRG_MEM_TYPE_LOCKBITS; + paddr = 0x3F00 + addr; + } else if (strcmp(mem->desc, "calibration") == 0) { + buf[1] = XPRG_MEM_TYPE_LOCKBITS; + paddr = 0x3F80 + addr; + } else if (strcmp(mem->desc, "signature") == 0) { + buf[1] = XPRG_MEM_TYPE_LOCKBITS; + paddr = 0x3FC0 + addr; + } + + buf[2] = (paddr>>24) & 0xFF; + buf[3] = (paddr>>16) & 0xFF; + buf[4] = (paddr>>8) & 0xFF; + buf[5] = paddr & 0xFF; + + buf[6] = 0; // Length MSB + buf[7] = 1; // Length LSB, 1 since we are reading only one byte + + if (jtag3_send_tpi(pgm, buf, len) < 0) + return -1; + + result = jtag3_recv_tpi(pgm, buf); + if (result < 0) { + pmsg_error("timeout/error communicating with programmer\n"); + return -1; + } + *value = buf[2]; + return 0; +} + +static int jtag3_chip_erase_tpi(const PROGRAMMER *pgm, const AVRPART *p) { + pmsg_error("jtag3_chip_erase_tpi() not implemented\n"); + return -1; +} + +static int jtag3_open_tpi(PROGRAMMER *pgm, const char *port) { + pmsg_notice2("jtag3_open_tpi()\n"); + + if (jtag3_open_common(pgm, port) < 0) + return -1; + return 0; +} + +void jtag3_close_tpi(PROGRAMMER *pgm) { + pmsg_notice2("jtag3_close_tpi() is empty. No action necessary.\n"); +} + const char jtag3_desc[] = "Atmel JTAGICE3"; @@ -2677,3 +2859,33 @@ void jtag3_updi_initpgm(PROGRAMMER *pgm) { } } +const char jtag3_tpi_desc[] = "Atmel JTAGICE3 in TPI mode"; + +void jtag3_tpi_initpgm(PROGRAMMER *pgm) { + strcpy(pgm->type, "JTAGICE3_TPI"); + + /* + * mandatory functions + */ + pgm->initialize = jtag3_initialize_tpi; + pgm->display = jtag3_display; + pgm->enable = jtag3_enable_tpi; + pgm->disable = jtag3_disable_tpi; + pgm->program_enable = jtag3_program_enable_dummy; + pgm->chip_erase = jtag3_chip_erase_tpi; + pgm->open = jtag3_open_tpi; + pgm->close = jtag3_close_tpi; + pgm->read_byte = jtag3_read_byte_tpi; + pgm->write_byte = jtag3_write_byte; + + /* + * optional functions + */ + pgm->paged_write = jtag3_paged_write; + pgm->paged_load = jtag3_paged_load; + pgm->print_parms = jtag3_print_parms; + pgm->setup = jtag3_setup; + pgm->teardown = jtag3_teardown; + pgm->page_size = 256; + pgm->flag = PGM_FL_IS_TPI; +} diff --git a/src/jtag3.h b/src/jtag3.h index 7ee95b5b..beb1fc3d 100644 --- a/src/jtag3.h +++ b/src/jtag3.h @@ -44,10 +44,12 @@ extern const char jtag3_desc[]; extern const char jtag3_dw_desc[]; extern const char jtag3_pdi_desc[]; extern const char jtag3_updi_desc[]; +extern const char jtag3_tpi_desc[]; void jtag3_initpgm(PROGRAMMER *pgm); void jtag3_dw_initpgm(PROGRAMMER *pgm); void jtag3_pdi_initpgm(PROGRAMMER *pgm); void jtag3_updi_initpgm(PROGRAMMER *pgm); +void jtag3_tpi_initpgm(PROGRAMMER *pgm); /* * These functions are referenced from stk500v2.c for JTAGICE3 in diff --git a/src/jtag3_private.h b/src/jtag3_private.h index 2e414c71..a1555117 100644 --- a/src/jtag3_private.h +++ b/src/jtag3_private.h @@ -96,6 +96,7 @@ #define SCOPE_GENERAL 0x01 #define SCOPE_AVR_ISP 0x11 #define SCOPE_AVR 0x12 +#define SCOPE_AVR_TPI 0x14 /* Info scope */ #define CMD3_GET_INFO 0x00 @@ -314,6 +315,57 @@ #define UPDI_ADDRESS_MODE_24BIT 1 #define FUSES_SYSCFG0_OFFSET 5 +// TPI Protocol commands +#define XPRG_CMD_ENTER_PROGMODE 0x01 +#define XPRG_CMD_LEAVE_PROGMODE 0x02 +#define XPRG_CMD_ERASE 0x03 +#define XPRG_CMD_WRITE_MEM 0x04 +#define XPRG_CMD_READ_MEM 0x05 +#define XPRG_CMD_CRC 0x06 +#define XPRG_CMD_SET_PARAM 0x07 + +// TPI Protocol responses +// Success +#define XPRG_ERR_OK 0x00 +// Errors +#define XPRG_ERR_FAILED 0x01 +#define XPRG_ERR_COLLISION 0x02 +#define XPRG_ERR_TIMEOUT 0x03 +#define XPRG_ERR_ILLEGAL_PARAM 0x04 +#define XPRG_ERR_UNKNOWN_COMMAND 0x10 + +// TPI Memory types +#define XPRG_MEM_TYPE_APPL 0x01 +#define XPRG_MEM_TYPE_BOOT 0x02 +#define XPRG_MEM_TYPE_EEPROM 0x03 +#define XPRG_MEM_TYPE_FUSE 0x04 +#define XPRG_MEM_TYPE_LOCKBITS 0x05 +#define XPRG_MEM_TYPE_USERSIG 0x06 +#define XPRG_MEM_TYPE_FACTORY_CALIBRATION 0x07 + +// TPI Erase modes +#define XPRG_ERASE_CHIP 0x01 +#define XPRG_ERASE_APP 0x02 +#define XPRG_ERASE_BOOT 0x03 +#define XPRG_ERASE_EEPROM 0x04 +#define XPRG_ERASE_APP_PAGE 0x05 +#define XPRG_ERASE_BOOT_PAGE 0x06 +#define XPRG_ERASE_EEPROM_PAGE 0x07 +#define XPRG_ERASE_USERSIG 0x08 +// Erase types for Tiny XPROG +#define XPRG_ERASE_CONFIG 0x09 + +// TPI Parameters +// XPROG parameters of different sizes +// 4-byte address +#define XPRG_PARAM_NVMBASE 0x01 +// 2-byte page size +#define XPRG_PARAM_EEPPAGESIZE 0x02 +// tiny TPI, 1-byte address +#define XPRG_PARAM_NVMCMD_ADDR 0x03 +#define XPRG_PARAM_NVMCSR_ADDR 0x04 + + #if !defined(JTAG3_PRIVATE_EXPORTED) struct mega_device_desc { diff --git a/src/pgm_type.c b/src/pgm_type.c index 45ce8dca..21c4f4a9 100644 --- a/src/pgm_type.c +++ b/src/pgm_type.c @@ -86,6 +86,7 @@ const PROGRAMMER_TYPE programmers_types[] = { // Name(s) the programmers call th {"jtagice3_updi", jtag3_updi_initpgm, jtag3_updi_desc}, // "JTAGICE3_UPDI" {"jtagice3_dw", jtag3_dw_initpgm, jtag3_dw_desc}, // "JTAGICE3_DW" {"jtagice3_isp", stk500v2_jtag3_initpgm, stk500v2_jtag3_desc}, // "JTAG3_ISP" + {"jtagice3_tpi", jtag3_tpi_initpgm, jtag3_tpi_desc}, // "JTAGICE3_TPI" {"linuxgpio", linuxgpio_initpgm, linuxgpio_desc}, // "linuxgpio" {"linuxspi", linuxspi_initpgm, linuxspi_desc}, // LINUXSPI {"micronucleus", micronucleus_initpgm, micronucleus_desc}, // "micronucleus" or "Micronucleus V2.0" diff --git a/src/stk500v2.c b/src/stk500v2.c index edf26cae..8c001ee4 100644 --- a/src/stk500v2.c +++ b/src/stk500v2.c @@ -3606,18 +3606,18 @@ static int stk600_xprog_program_enable(const PROGRAMMER *pgm, const AVRPART *p) return -1; buf[0] = XPRG_CMD_SET_PARAM; - buf[1] = XPRG_PARAM_TPI_3; + buf[1] = XPRG_PARAM_NVMCMD_ADDR; buf[2] = 51; if (stk600_xprog_command(pgm, buf, 3, 2) < 0) { - pmsg_error("XPRG_CMD_SET_PARAM(XPRG_PARAM_TPI_3) failed\n"); + pmsg_error("XPRG_CMD_SET_PARAM(XPRG_PARAM_NVMCMD_ADDR) failed\n"); return -1; } buf[0] = XPRG_CMD_SET_PARAM; - buf[1] = XPRG_PARAM_TPI_4; + buf[1] = XPRG_PARAM_NVMCSR_ADDR; buf[2] = 50; if (stk600_xprog_command(pgm, buf, 3, 2) < 0) { - pmsg_error("XPRG_CMD_SET_PARAM(XPRG_PARAM_TPI_4) failed\n"); + pmsg_error("XPRG_CMD_SET_PARAM(XPRG_PARAM_NVMCSR_ADDR) failed\n"); return -1; } } else { diff --git a/src/stk500v2_private.h b/src/stk500v2_private.h index 5531a269..1e499792 100644 --- a/src/stk500v2_private.h +++ b/src/stk500v2_private.h @@ -223,35 +223,6 @@ #define XPRG_MODE_JTAG 1 #define XPRG_MODE_TPI 2 -// XPROG commands -#define XPRG_CMD_ENTER_PROGMODE 0x01 -#define XPRG_CMD_LEAVE_PROGMODE 0x02 -#define XPRG_CMD_ERASE 0x03 -#define XPRG_CMD_WRITE_MEM 0x04 -#define XPRG_CMD_READ_MEM 0x05 -#define XPRG_CMD_CRC 0x06 -#define XPRG_CMD_SET_PARAM 0x07 - -// Memory types -#define XPRG_MEM_TYPE_APPL 1 -#define XPRG_MEM_TYPE_BOOT 2 -#define XPRG_MEM_TYPE_EEPROM 3 -#define XPRG_MEM_TYPE_FUSE 4 -#define XPRG_MEM_TYPE_LOCKBITS 5 -#define XPRG_MEM_TYPE_USERSIG 6 -#define XPRG_MEM_TYPE_FACTORY_CALIBRATION 7 - -// Erase types -#define XPRG_ERASE_CHIP 1 -#define XPRG_ERASE_APP 2 -#define XPRG_ERASE_BOOT 3 -#define XPRG_ERASE_EEPROM 4 -#define XPRG_ERASE_APP_PAGE 5 -#define XPRG_ERASE_BOOT_PAGE 6 -#define XPRG_ERASE_EEPROM_PAGE 7 -#define XPRG_ERASE_USERSIG 8 -#define XPRG_ERASE_CONFIG 9 // TPI only, prepare fuse write - // Write mode flags #define XPRG_MEM_WRITE_ERASE 0 #define XPRG_MEM_WRITE_WRITE 1 @@ -261,22 +232,6 @@ #define XPRG_CRC_BOOT 2 #define XPRG_CRC_FLASH 3 -// Error codes -#define XPRG_ERR_OK 0 -#define XPRG_ERR_FAILED 1 -#define XPRG_ERR_COLLISION 2 -#define XPRG_ERR_TIMEOUT 3 - -// XPROG parameters of different sizes -// 4-byte address -#define XPRG_PARAM_NVMBASE 0x01 -// 2-byte page size -#define XPRG_PARAM_EEPPAGESIZE 0x02 -// 1-byte, undocumented TPI param -#define XPRG_PARAM_TPI_3 0x03 -// 1-byte, undocumented TPI param -#define XPRG_PARAM_TPI_4 0x04 - // *****************[ STK answer constants ]*************************** #define ANSWER_CKSUM_ERROR 0xB0 From 32a6ca39e4bb4f5319bece6cbf60d0f45f81136e Mon Sep 17 00:00:00 2001 From: Jan Egil Ruud Date: Tue, 22 Nov 2022 13:05:14 +0100 Subject: [PATCH 02/22] Cleaned up whitespace in jtag3.c so it at least is consistent within the file. --- src/jtag3.c | 545 ++++++++++++++++++++++++---------------------------- src/jtag3.h | 10 +- 2 files changed, 257 insertions(+), 298 deletions(-) diff --git a/src/jtag3.c b/src/jtag3.c index de23a407..b2809983 100644 --- a/src/jtag3.c +++ b/src/jtag3.c @@ -63,7 +63,7 @@ struct pdata unsigned long eeprom_pageaddr; unsigned int eeprom_pagesize; - int prog_enabled; /* Cached value of PROGRAMMING status. */ + int prog_enabled; /* Cached value of PROGRAMMING status. */ /* JTAG chain stuff */ unsigned char jtagchain[4]; @@ -84,7 +84,7 @@ struct pdata * pgm->flag is marked as "for private use of the programmer". * The following defines this programmer's use of that field. */ -#define PGM_FL_IS_DW (0x0001) +#define PGM_FL_IS_DW (0x0001) #define PGM_FL_IS_PDI (0x0002) #define PGM_FL_IS_JTAG (0x0004) #define PGM_FL_IS_EDBG (0x0008) @@ -197,9 +197,9 @@ static void jtag3_prmsg(const PROGRAMMER *pgm, unsigned char *data, size_t len) for (i = 0; i < len; i++) { msg_trace("%02x ", data[i]); if (i % 16 == 15) - msg_trace("\n"); + msg_trace("\n"); else - msg_trace(" "); + msg_trace(" "); } if (i % 16 != 0) msg_trace("\n"); @@ -237,47 +237,45 @@ static void jtag3_prmsg(const PROGRAMMER *pgm, unsigned char *data, size_t len) msg_info("FAILED"); if (len > 3) { - char reason[50]; - sprintf(reason, "0x%02x", data[3]); - switch (data[3]) - { - case RSP3_FAIL_NO_ANSWER: - strcpy(reason, "target does not answer"); - break; + char reason[50]; + sprintf(reason, "0x%02x", data[3]); + switch (data[3]) { + case RSP3_FAIL_NO_ANSWER: + strcpy(reason, "target does not answer"); + break; - case RSP3_FAIL_NO_TARGET_POWER: - strcpy(reason, "no target power"); - break; + case RSP3_FAIL_NO_TARGET_POWER: + strcpy(reason, "no target power"); + break; - case RSP3_FAIL_NOT_UNDERSTOOD: - strcpy(reason, "command not understood"); - break; + case RSP3_FAIL_NOT_UNDERSTOOD: + strcpy(reason, "command not understood"); + break; - case RSP3_FAIL_WRONG_MODE: - strcpy(reason, "wrong (programming) mode"); - break; + case RSP3_FAIL_WRONG_MODE: + strcpy(reason, "wrong (programming) mode"); + break; - case RSP3_FAIL_PDI: - strcpy(reason, "PDI failure"); - break; + case RSP3_FAIL_PDI: + strcpy(reason, "PDI failure"); + break; - case RSP3_FAIL_UNSUPP_MEMORY: - strcpy(reason, "unsupported memory type"); - break; + case RSP3_FAIL_UNSUPP_MEMORY: + strcpy(reason, "unsupported memory type"); + break; - case RSP3_FAIL_WRONG_LENGTH: - strcpy(reason, "wrong length in memory access"); - break; + case RSP3_FAIL_WRONG_LENGTH: + strcpy(reason, "wrong length in memory access"); + break; - case RSP3_FAIL_DEBUGWIRE: - strcpy(reason, "debugWIRE communication failed"); - break; - } - msg_info(", reason: %s\n", reason); + case RSP3_FAIL_DEBUGWIRE: + strcpy(reason, "debugWIRE communication failed"); + break; + } + msg_info(", reason: %s\n", reason); } - else - { - msg_info(", unspecified reason\n"); + else { + msg_info(", unspecified reason\n"); } break; @@ -289,29 +287,27 @@ static void jtag3_prmsg(const PROGRAMMER *pgm, unsigned char *data, size_t len) case RSP3_INFO: msg_info("Info returned:\n"); for (i = 2; i < len; i++) { - if (isprint(data[i])) - msg_info("%c", data[i]); - else - msg_info("\\%03o", data[i]); + if (isprint(data[i])) + msg_info("%c", data[i]); + else + msg_info("\\%03o", data[i]); } msg_info("\n"); break; case RSP3_PC: - if (len < 7) - { - msg_info("PC reply too short\n"); + if (len < 7) { + msg_info("PC reply too short\n"); } - else - { - unsigned long pc = (data[6] << 24) | (data[5] << 16) - | (data[4] << 8) | data[3]; - msg_info("PC 0x%0lx\n", pc); + else { + unsigned long pc = (data[6] << 24) | (data[5] << 16) + | (data[4] << 8) | data[3]; + msg_info("PC 0x%0lx\n", pc); } break; - default: - msg_info("unknown message 0x%02x\n", data[1]); + default: + msg_info("unknown message 0x%02x\n", data[1]); } } @@ -332,9 +328,9 @@ static void jtag3_prevent(const PROGRAMMER *pgm, unsigned char *data, size_t len for (i = 0; i < len; i++) { msg_trace("%02x ", data[i]); if (i % 16 == 15) - msg_trace("\n"); + msg_trace("\n"); else - msg_trace(" "); + msg_trace(" "); } if (i % 16 != 0) msg_trace("\n"); @@ -361,58 +357,56 @@ static void jtag3_prevent(const PROGRAMMER *pgm, unsigned char *data, size_t len } switch (data[5]) { - case EVT3_BREAK: - msg_info("BREAK"); - if (len >= 11) { - msg_info(", PC = 0x%lx, reason ", b4_to_u32(data + 6)); - switch (data[10]) { - case 0x00: - msg_info("unspecified"); - break; - case 0x01: - msg_info("program break"); - break; - case 0x02: - msg_info("data break PDSB"); - break; - case 0x03: - msg_info("data break PDMSB"); - break; - default: - msg_info("unknown: 0x%02x", data[10]); + case EVT3_BREAK: + msg_info("BREAK"); + if (len >= 11) { + msg_info(", PC = 0x%lx, reason ", b4_to_u32(data + 6)); + switch (data[10]) { + case 0x00: + msg_info("unspecified"); + break; + case 0x01: + msg_info("program break"); + break; + case 0x02: + msg_info("data break PDSB"); + break; + case 0x03: + msg_info("data break PDMSB"); + break; + default: + msg_info("unknown: 0x%02x", data[10]); + } + /* There are two more bytes of data which always appear to be + * 0x01, 0x00. Purpose unknown. */ } - /* There are two more bytes of data which always appear to be - * 0x01, 0x00. Purpose unknown. */ - } - break; + break; - case EVT3_SLEEP: - if (len >= 8 && data[7] == 0) - msg_info("sleeping"); - else if (len >= 8 && data[7] == 1) - msg_info("wakeup"); - else - msg_info("unknown SLEEP event"); - break; + case EVT3_SLEEP: + if (len >= 8 && data[7] == 0) + msg_info("sleeping"); + else if (len >= 8 && data[7] == 1) + msg_info("wakeup"); + else + msg_info("unknown SLEEP event"); + break; - case EVT3_POWER: - if (len >= 8 && data[7] == 0) - msg_info("power-down"); - else if (len >= 8 && data[7] == 1) - msg_info("power-up"); - else - msg_info("unknown POWER event"); - break; + case EVT3_POWER: + if (len >= 8 && data[7] == 0) + msg_info("power-down"); + else if (len >= 8 && data[7] == 1) + msg_info("power-up"); + else + msg_info("unknown POWER event"); + break; - default: - msg_info("UNKNOWN 0x%02x", data[5]); - break; + default: + msg_info("UNKNOWN 0x%02x", data[5]); + break; } msg_info("\n"); } - - int jtag3_send(const PROGRAMMER *pgm, unsigned char *data, size_t len) { unsigned char *buf; @@ -422,11 +416,10 @@ int jtag3_send(const PROGRAMMER *pgm, unsigned char *data, size_t len) { msg_debug("\n"); pmsg_debug("jtag3_send(): sending %lu bytes\n", (unsigned long) len); - if ((buf = malloc(len + 4)) == NULL) - { - pmsg_error("out of memory"); - return -1; - } + if ((buf = malloc(len + 4)) == NULL) { + pmsg_error("out of memory"); + return -1; + } buf[0] = TOKEN; buf[1] = 0; /* dummy */ @@ -449,11 +442,10 @@ static int jtag3_edbg_send(const PROGRAMMER *pgm, unsigned char *data, size_t le unsigned char status[USBDEV_MAX_XFER_3]; int rv; - if (verbose >= 4) - { - memset(buf, 0, USBDEV_MAX_XFER_3); - memset(status, 0, USBDEV_MAX_XFER_3); - } + if (verbose >= 4) { + memset(buf, 0, USBDEV_MAX_XFER_3); + memset(status, 0, USBDEV_MAX_XFER_3); + } msg_debug("\n"); pmsg_debug("jtag3_edbg_send(): sending %lu bytes\n", (unsigned long) len); @@ -461,60 +453,55 @@ static int jtag3_edbg_send(const PROGRAMMER *pgm, unsigned char *data, size_t le /* 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) - { - pmsg_debug("jtag3_edbg_send(): fragmenting into %d packets\n", nfragments); - } + if (nfragments > 1) { + pmsg_debug("jtag3_edbg_send(): fragmenting into %d packets\n", nfragments); + } int frag; - for (frag = 0; frag < nfragments; frag++) - { - int this_len; + 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[1] = ((frag + 1) << 4) | nfragments; + /* All fragments have the (CMSIS-DAP layer) CMD, the fragment + * identifier, and the length field. */ + buf[0] = EDBG_VENDOR_AVR_CMD; + buf[1] = ((frag + 1) << 4) | nfragments; - 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[5] = 0; /* dummy */ - u16_to_b2(buf + 6, PDATA(pgm)->command_sequence); - 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, max_xfer) != 0) { - pmsg_notice("jtag3_edbg_send(): unable to send command to serial port\n"); - return -1; - } - rv = serial_recv(&pgm->fd, status, max_xfer); - - if (rv < 0) { - /* timeout in receive */ - pmsg_notice2("jtag3_edbg_send(): timeout receiving packet\n"); - return -1; - } - if (status[0] != EDBG_VENDOR_AVR_CMD || - (frag == nfragments - 1 && status[1] != 0x01)) - { - /* what to do in this case? */ - pmsg_notice("jtag3_edbg_send(): unexpected response 0x%02x, 0x%02x\n", status[0], status[1]); - } - data += this_len; - len -= this_len; + 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[5] = 0; /* dummy */ + u16_to_b2(buf + 6, PDATA(pgm)->command_sequence); + 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, max_xfer) != 0) { + pmsg_notice("jtag3_edbg_send(): unable to send command to serial port\n"); + return -1; + } + rv = serial_recv(&pgm->fd, status, max_xfer); + + if (rv < 0) { + /* timeout in receive */ + pmsg_notice2("jtag3_edbg_send(): timeout receiving packet\n"); + return -1; + } + if (status[0] != EDBG_VENDOR_AVR_CMD || + (frag == nfragments - 1 && status[1] != 0x01)) { + /* what to do in this case? */ + pmsg_notice("jtag3_edbg_send(): unexpected response 0x%02x, 0x%02x\n", status[0], status[1]); + } + data += this_len; + len -= this_len; + } return 0; } @@ -772,7 +759,7 @@ int jtag3_recv(const PROGRAMMER *pgm, unsigned char **msg) { if ((rv & USB_RECV_FLAG_EVENT) != 0) { if (verbose >= 3) - jtag3_prevent(pgm, *msg, rv & USB_RECV_LENGTH_MASK); + jtag3_prevent(pgm, *msg, rv & USB_RECV_LENGTH_MASK); free(*msg); continue; @@ -784,7 +771,7 @@ int jtag3_recv(const PROGRAMMER *pgm, unsigned char **msg) { "Got message seqno %d (command_sequence == %d)\n", r_seqno, PDATA(pgm)->command_sequence); if (r_seqno == PDATA(pgm)->command_sequence) { if (++(PDATA(pgm)->command_sequence) == 0xffff) - PDATA(pgm)->command_sequence = 0; + PDATA(pgm)->command_sequence = 0; /* * We move the payload to the beginning of the buffer, to make * the job easier for the caller. We have to return the @@ -803,8 +790,7 @@ int jtag3_recv(const PROGRAMMER *pgm, unsigned char **msg) { } int jtag3_command(const PROGRAMMER *pgm, unsigned char *cmd, unsigned int cmdlen, - unsigned char **resp, const char *descr) -{ + unsigned char **resp, const char *descr) { int status; unsigned char c; @@ -825,8 +811,8 @@ int jtag3_command(const PROGRAMMER *pgm, unsigned char *cmd, unsigned int cmdlen c = (*resp)[1] & RSP3_STATUS_MASK; if (c != RSP3_OK) { - if ((c == RSP3_FAILED) && ((*resp)[3] == RSP3_FAIL_OCD_LOCKED || - (*resp)[3] == RSP3_FAIL_CRC_FAILURE)) { + if ((c == RSP3_FAILED) && + ((*resp)[3] == RSP3_FAIL_OCD_LOCKED || (*resp)[3] == RSP3_FAIL_CRC_FAILURE)) { pmsg_error("device is locked; chip erase required to unlock\n"); } else { pmsg_notice("bad response to %s command: 0x%02x\n", descr, c); @@ -851,9 +837,9 @@ int jtag3_getsync(const PROGRAMMER *pgm, int mode) { * firmware bug where they complained about it. */ if ((pgm->flag & PGM_FL_IS_EDBG) && !matches(ldata(lfirst(pgm->id)), "xplainedmini")) { - if (jtag3_edbg_prepare(pgm) < 0) { - return -1; - } + if (jtag3_edbg_prepare(pgm) < 0) { + return -1; + } } /* Get the sign-on information. */ @@ -919,9 +905,7 @@ static int jtag3_unlock_erase_key(const PROGRAMMER *pgm, const AVRPART *p) { * There is no chip erase functionality in debugWire mode. */ static int jtag3_chip_erase_dw(const PROGRAMMER *pgm, const AVRPART *p) { - pmsg_error("chip erase not supported in debugWire mode\n"); - return 0; } @@ -971,15 +955,15 @@ static int jtag3_program_disable(const PROGRAMMER *pgm) { } static int jtag3_set_sck_xmega_pdi(const PROGRAMMER *pgm, unsigned char *clk) { - return jtag3_setparm(pgm, SCOPE_AVR, 1, PARM3_CLK_XMEGA_PDI, clk, 2); + return jtag3_setparm(pgm, SCOPE_AVR, 1, PARM3_CLK_XMEGA_PDI, clk, 2); } static int jtag3_set_sck_xmega_jtag(const PROGRAMMER *pgm, unsigned char *clk) { - return jtag3_setparm(pgm, SCOPE_AVR, 1, PARM3_CLK_XMEGA_JTAG, clk, 2); + return jtag3_setparm(pgm, SCOPE_AVR, 1, PARM3_CLK_XMEGA_JTAG, clk, 2); } static int jtag3_set_sck_mega_jtag(const PROGRAMMER *pgm, unsigned char *clk) { - return jtag3_setparm(pgm, SCOPE_AVR, 1, PARM3_CLK_MEGA_PROG, clk, 2); + return jtag3_setparm(pgm, SCOPE_AVR, 1, PARM3_CLK_MEGA_PROG, clk, 2); } @@ -1068,8 +1052,7 @@ static int jtag3_initialize(const PROGRAMMER *pgm, const AVRPART *p) { else PDATA(pgm)->set_sck = jtag3_set_sck_mega_jtag; } - if (pgm->bitclock != 0.0 && PDATA(pgm)->set_sck != NULL) - { + if (pgm->bitclock != 0.0 && PDATA(pgm)->set_sck != NULL) { unsigned int clock = 1E-3 / pgm->bitclock; /* kHz */ pmsg_notice2("jtag3_initialize(): " "trying to set JTAG clock to %u kHz\n", clock); @@ -1079,8 +1062,7 @@ static int jtag3_initialize(const PROGRAMMER *pgm, const AVRPART *p) { return -1; } jtag3_print_parms1(pgm, progbuf, stderr); - if (conn == PARM3_CONN_JTAG) - { + if (conn == PARM3_CONN_JTAG) { pmsg_notice2("jtag3_initialize(): " "trying to set JTAG daisy-chain info to %d,%d,%d,%d\n", PDATA(pgm)->jtagchain[0], PDATA(pgm)->jtagchain[1], @@ -1090,8 +1072,7 @@ static int jtag3_initialize(const PROGRAMMER *pgm, const AVRPART *p) { } /* set device descriptor data */ - if ((p->prog_modes & PM_PDI)) - { + if ((p->prog_modes & PM_PDI)) { struct xmega_device_desc xd; LNODEID ln; AVRMEM * m; @@ -1102,41 +1083,40 @@ static int jtag3_initialize(const PROGRAMMER *pgm, const AVRPART *p) { for (ln = lfirst(p->mem); ln; ln = lnext(ln)) { m = ldata(ln); if (strcmp(m->desc, "flash") == 0) { - if (m->readsize != 0 && m->readsize < m->page_size) - PDATA(pgm)->flash_pagesize = m->readsize; - else - PDATA(pgm)->flash_pagesize = m->page_size; - u16_to_b2(xd.flash_page_size, m->page_size); + if (m->readsize != 0 && m->readsize < m->page_size) + PDATA(pgm)->flash_pagesize = m->readsize; + else + PDATA(pgm)->flash_pagesize = m->page_size; + u16_to_b2(xd.flash_page_size, m->page_size); } else if (strcmp(m->desc, "eeprom") == 0) { - PDATA(pgm)->eeprom_pagesize = m->page_size; - xd.eeprom_page_size = m->page_size; - u16_to_b2(xd.eeprom_size, m->size); - u32_to_b4(xd.nvm_eeprom_offset, m->offset); + PDATA(pgm)->eeprom_pagesize = m->page_size; + xd.eeprom_page_size = m->page_size; + u16_to_b2(xd.eeprom_size, m->size); + u32_to_b4(xd.nvm_eeprom_offset, m->offset); } else if (strcmp(m->desc, "application") == 0) { - u32_to_b4(xd.app_size, m->size); - u32_to_b4(xd.nvm_app_offset, m->offset); + u32_to_b4(xd.app_size, m->size); + u32_to_b4(xd.nvm_app_offset, m->offset); } else if (strcmp(m->desc, "boot") == 0) { - u16_to_b2(xd.boot_size, m->size); - u32_to_b4(xd.nvm_boot_offset, m->offset); + u16_to_b2(xd.boot_size, m->size); + u32_to_b4(xd.nvm_boot_offset, m->offset); } else if (strcmp(m->desc, "fuse1") == 0) { - u32_to_b4(xd.nvm_fuse_offset, m->offset & ~7); + u32_to_b4(xd.nvm_fuse_offset, m->offset & ~7); } else if (matches(m->desc, "lock")) { - u32_to_b4(xd.nvm_lock_offset, m->offset); + u32_to_b4(xd.nvm_lock_offset, m->offset); } else if (strcmp(m->desc, "usersig") == 0 || strcmp(m->desc, "userrow") == 0) { - u32_to_b4(xd.nvm_user_sig_offset, m->offset); + u32_to_b4(xd.nvm_user_sig_offset, m->offset); } else if (strcmp(m->desc, "prodsig") == 0) { - u32_to_b4(xd.nvm_prod_sig_offset, m->offset); + u32_to_b4(xd.nvm_prod_sig_offset, m->offset); } else if (strcmp(m->desc, "data") == 0) { - u32_to_b4(xd.nvm_data_offset, m->offset); + u32_to_b4(xd.nvm_data_offset, m->offset); } } if (jtag3_setparm(pgm, SCOPE_AVR, 2, PARM3_DEVICEDESC, (unsigned char *)&xd, sizeof xd) < 0) return -1; } - else if ((p->prog_modes & PM_UPDI)) - { + else if ((p->prog_modes & PM_UPDI)) { struct updi_device_desc xd; LNODEID ln; AVRMEM *m; @@ -1145,11 +1125,9 @@ static int jtag3_initialize(const PROGRAMMER *pgm, const AVRPART *p) { u16_to_b2(xd.ocd_base_addr, p->ocd_base); xd.hvupdi_variant = p->hvupdi_variant; - for (ln = lfirst(p->mem); ln; ln = lnext(ln)) - { + for (ln = lfirst(p->mem); ln; ln = lnext(ln)) { m = ldata(ln); - if (strcmp(m->desc, "flash") == 0) - { + if (strcmp(m->desc, "flash") == 0) { u16_to_b2(xd.prog_base, m->offset&0xFFFF); xd.prog_base_msb = m->offset>>16; @@ -1167,8 +1145,7 @@ static int jtag3_initialize(const PROGRAMMER *pgm, const AVRPART *p) { else xd.address_mode = UPDI_ADDRESS_MODE_16BIT; } - else if (strcmp(m->desc, "eeprom") == 0) - { + else if (strcmp(m->desc, "eeprom") == 0) { PDATA(pgm)->eeprom_pagesize = m->page_size; xd.eeprom_page_size = m->page_size; @@ -1176,24 +1153,20 @@ static int jtag3_initialize(const PROGRAMMER *pgm, const AVRPART *p) { u16_to_b2(xd.eeprom_base, m->offset); } else if (strcmp(m->desc, "usersig") == 0 || - strcmp(m->desc, "userrow") == 0) - { + strcmp(m->desc, "userrow") == 0) { u16_to_b2(xd.user_sig_bytes, m->size); u16_to_b2(xd.user_sig_base, m->offset); } - else if (strcmp(m->desc, "signature") == 0) - { + else if (strcmp(m->desc, "signature") == 0) { u16_to_b2(xd.signature_base, m->offset); xd.device_id[0] = p->signature[1]; xd.device_id[1] = p->signature[2]; } - else if (strcmp(m->desc, "fuses") == 0) - { + else if (strcmp(m->desc, "fuses") == 0) { xd.fuses_bytes = m->size; u16_to_b2(xd.fuses_base, m->offset); } - else if (strcmp(m->desc, "lock") == 0) - { + else if (strcmp(m->desc, "lock") == 0) { u16_to_b2(xd.lockbits_base, m->offset); } } @@ -1206,7 +1179,7 @@ static int jtag3_initialize(const PROGRAMMER *pgm, const AVRPART *p) { for (LNODEID ln = lfirst(pgm->hvupdi_support); ln; ln = lnext(ln)) { if(*(int *) ldata(ln) == p->hvupdi_variant) { pmsg_notice("sending HV pulse to targets %s pin\n", - p->hvupdi_variant == HV_UPDI_VARIANT_0? "UPDI": "RESET"); + p->hvupdi_variant == HV_UPDI_VARIANT_0? "UPDI": "RESET"); parm[0] = PARM3_UPDI_HV_SIMPLE_PULSE; break; } @@ -1251,8 +1224,7 @@ static int jtag3_initialize(const PROGRAMMER *pgm, const AVRPART *p) { if (jtag3_setparm(pgm, SCOPE_AVR, 2, PARM3_DEVICEDESC, (unsigned char *)&xd, sizeof xd) < 0) return -1; } - else - { + else { struct mega_device_desc md; LNODEID ln; AVRMEM * m; @@ -1263,18 +1235,18 @@ static int jtag3_initialize(const PROGRAMMER *pgm, const AVRPART *p) { for (ln = lfirst(p->mem); ln; ln = lnext(ln)) { m = ldata(ln); if (strcmp(m->desc, "flash") == 0) { - if (m->readsize != 0 && m->readsize < m->page_size) - PDATA(pgm)->flash_pagesize = m->readsize; - else - PDATA(pgm)->flash_pagesize = m->page_size; - u16_to_b2(md.flash_page_size, m->page_size); - u32_to_b4(md.flash_size, (flashsize = m->size)); - // do we need it? just a wild guess - u32_to_b4(md.boot_address, (m->size - m->page_size * 4) / 2); + if (m->readsize != 0 && m->readsize < m->page_size) + PDATA(pgm)->flash_pagesize = m->readsize; + else + PDATA(pgm)->flash_pagesize = m->page_size; + u16_to_b2(md.flash_page_size, m->page_size); + u32_to_b4(md.flash_size, (flashsize = m->size)); + // do we need it? just a wild guess + u32_to_b4(md.boot_address, (m->size - m->page_size * 4) / 2); } else if (strcmp(m->desc, "eeprom") == 0) { - PDATA(pgm)->eeprom_pagesize = m->page_size; - md.eeprom_page_size = m->page_size; - u16_to_b2(md.eeprom_size, m->size); + PDATA(pgm)->eeprom_pagesize = m->page_size; + md.eeprom_page_size = m->page_size; + u16_to_b2(md.eeprom_size, m->size); } } @@ -1284,11 +1256,11 @@ static int jtag3_initialize(const PROGRAMMER *pgm, const AVRPART *p) { /* lacking a proper definition, guess the OCD revision */ if (p->prog_modes & PM_debugWIRE) - ocdrev = 1; /* exception: ATtiny13, 2313, 4313 */ + ocdrev = 1; /* exception: ATtiny13, 2313, 4313 */ else if (flashsize > 128 * 1024) - ocdrev = 4; + ocdrev = 4; else - ocdrev = 3; /* many exceptions from that, actually */ + ocdrev = 3; /* many exceptions from that, actually */ pmsg_warning("part definition for %s lacks ocdrev; guessing %d\n", p->desc, ocdrev); md.ocd_revision = ocdrev; } else { @@ -1316,7 +1288,7 @@ static int jtag3_initialize(const PROGRAMMER *pgm, const AVRPART *p) { cmd[0] = SCOPE_AVR; cmd[1] = CMD3_SIGN_ON; cmd[2] = 0; - cmd[3] = use_ext_reset; /* external reset */ + cmd[3] = use_ext_reset; /* external reset */ if ((status = jtag3_command(pgm, cmd, 4, &resp, "AVR sign-on")) >= 0) break; @@ -1325,9 +1297,9 @@ static int jtag3_initialize(const PROGRAMMER *pgm, const AVRPART *p) { } if (use_ext_reset > 1) { - if(strcmp(pgm->type, "JTAGICE3") == 0 && (p->prog_modes & (PM_JTAG | PM_JTAGmkI | PM_XMEGAJTAG | PM_AVR32JTAG))) - pmsg_error("JTAGEN fuse disabled?\n"); - return -1; + if(strcmp(pgm->type, "JTAGICE3") == 0 && (p->prog_modes & (PM_JTAG | PM_JTAGmkI | PM_XMEGAJTAG | PM_AVR32JTAG))) + pmsg_error("JTAGEN fuse disabled?\n"); + return -1; } /* @@ -1346,12 +1318,12 @@ static int jtag3_initialize(const PROGRAMMER *pgm, const AVRPART *p) { if (p->prog_modes & PM_UPDI) { /* Partial Family_ID has been returned */ pmsg_notice("partial Family_ID returned: \"%c%c%c%c\"\n", - resp[3], resp[4], resp[5], resp[6]); + resp[3], resp[4], resp[5], resp[6]); } else /* JTAG ID has been returned */ pmsg_notice("JTAG ID returned: 0x%02x 0x%02x 0x%02x 0x%02x\n", - resp[3], resp[4], resp[5], resp[6]); + resp[3], resp[4], resp[5], resp[6]); } free(resp); @@ -1413,15 +1385,14 @@ static int jtag3_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) { if (matches(extended_param, "jtagchain=")) { unsigned int ub, ua, bb, ba; - if (sscanf(extended_param, "jtagchain=%u,%u,%u,%u", &ub, &ua, &bb, &ba) - != 4) { + if (sscanf(extended_param, "jtagchain=%u,%u,%u,%u", &ub, &ua, &bb, &ba) != 4) { pmsg_error("invalid JTAG chain '%s'\n", extended_param); rv = -1; continue; } pmsg_notice2("jtag3_parseextparms(): JTAG chain parsed as:\n"); imsg_notice2("%u units before, %u units after, %u bits before, %u bits after\n", - ub, ua, bb, ba); + ub, ua, bb, ba); PDATA(pgm)->jtagchain[0] = ub; PDATA(pgm)->jtagchain[1] = ua; PDATA(pgm)->jtagchain[2] = bb; @@ -1485,7 +1456,7 @@ int jtag3_open_common(PROGRAMMER *pgm, const char *port) { rv = serial_open(port, pinfo, &pgm->fd); } if (rv < 0) { -#endif /* HAVE_LIBHIDAPI */ +#endif /* HAVE_LIBHIDAPI */ #if defined(HAVE_LIBUSB) serdev = &usb_serdev_frame; for (usbpid = lfirst(pgm->usbpid); rv < 0 && usbpid != NULL; usbpid = lnext(usbpid)) { @@ -1499,7 +1470,7 @@ int jtag3_open_common(PROGRAMMER *pgm, const char *port) { strcpy(pgm->port, port); rv = serial_open(port, pinfo, &pgm->fd); } -#endif /* HAVE_LIBUSB */ +#endif /* HAVE_LIBUSB */ #if defined(HAVE_LIBHIDAPI) } #endif @@ -1529,7 +1500,7 @@ int jtag3_open_common(PROGRAMMER *pgm, const char *port) { } } pmsg_error("did not find any device matching VID 0x%04x and PID list: ", - (unsigned) pinfo.usbinfo.vid); + (unsigned) pinfo.usbinfo.vid); int notfirst = 0; for (usbpid = lfirst(pgm->usbpid); usbpid != NULL; usbpid = lnext(usbpid)) { if (notfirst) @@ -1542,8 +1513,7 @@ int jtag3_open_common(PROGRAMMER *pgm, const char *port) { return -1; } - if (pgm->fd.usb.eep == 0) - { + 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; @@ -1614,8 +1584,7 @@ static int jtag3_open_updi(PROGRAMMER *pgm, const char *port) { return 0; } -void jtag3_close(PROGRAMMER * pgm) -{ +void jtag3_close(PROGRAMMER * pgm) { unsigned char buf[4], *resp; pmsg_notice2("jtag3_close()\n"); @@ -1637,7 +1606,7 @@ void jtag3_close(PROGRAMMER * pgm) * firmware bug where they complained about it. */ if ((pgm->flag & PGM_FL_IS_EDBG) && !matches(ldata(lfirst(pgm->id)), "xplainedmini")) { - jtag3_edbg_signoff(pgm); + jtag3_edbg_signoff(pgm); } serial_close(&pgm->fd); @@ -1645,8 +1614,7 @@ void jtag3_close(PROGRAMMER * pgm) } static int jtag3_page_erase(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m, - unsigned int addr) -{ + unsigned int addr) { unsigned char cmd[8], *resp; pmsg_notice2("jtag3_page_erase(.., %s, 0x%x)\n", m->desc, addr); @@ -1693,8 +1661,7 @@ static int jtag3_page_erase(const PROGRAMMER *pgm, const AVRPART *p, const AVRME 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) -{ + unsigned int addr, unsigned int n_bytes) { unsigned int block_size; unsigned int maxaddr = addr + n_bytes; unsigned char *cmd; @@ -1712,7 +1679,8 @@ static int jtag3_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVRM if (!(pgm->flag & PGM_FL_IS_DW) && jtag3_program_enable(pgm) < 0) return -1; - if (page_size == 0) page_size = 256; + if (page_size == 0) + page_size = 256; if ((cmd = malloc(page_size + 13)) == NULL) { pmsg_error("out of memory\n"); @@ -1735,11 +1703,11 @@ static int jtag3_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVRM * DW mode. Use jtag3_write_byte() instead. */ for (; addr < maxaddr; addr++) { - status = jtag3_write_byte(pgm, p, m, addr, m->buf[addr]); - if (status < 0) { - free(cmd); - return -1; - } + status = jtag3_write_byte(pgm, p, m, addr, m->buf[addr]); + if (status < 0) { + free(cmd); + return -1; + } } free(cmd); return n_bytes; @@ -1783,7 +1751,7 @@ static int jtag3_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVRM memcpy(cmd + 13, m->buf + addr, block_size); if ((status = jtag3_command(pgm, cmd, page_size + 13, - &resp, "write memory")) < 0) { + &resp, "write memory")) < 0) { free(cmd); serial_recv_timeout = otimeout; return -1; @@ -1799,9 +1767,8 @@ static int jtag3_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVRM } static int jtag3_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m, - unsigned int page_size, - unsigned int addr, unsigned int n_bytes) -{ + unsigned int page_size, + unsigned int addr, unsigned int n_bytes) { unsigned int block_size; unsigned int maxaddr = addr + n_bytes; unsigned char cmd[12]; @@ -1810,7 +1777,7 @@ static int jtag3_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AVRME long otimeout = serial_recv_timeout; pmsg_notice2("jtag3_paged_load(.., %s, %d, 0x%04x, %d)\n", - m->desc, page_size, addr, n_bytes); + m->desc, page_size, addr, n_bytes); block_size = jtag3_memaddr(pgm, p, m, addr); if(block_size != addr) @@ -1856,7 +1823,7 @@ static int jtag3_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AVRME else block_size = page_size; pmsg_debug("jtag3_paged_load(): " - "block_size at addr %d is %d\n", addr, block_size); + "block_size at addr %d is %d\n", addr, block_size); if (dynamic_memtype) cmd[3] = jtag3_memtype(pgm, p, addr); @@ -1868,7 +1835,7 @@ static int jtag3_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AVRME return -1; if (resp[1] != RSP3_DATA || - status < block_size + 4) { + status < block_size + 4) { pmsg_error("wrong/short reply to read memory command\n"); serial_recv_timeout = otimeout; free(resp); @@ -1883,8 +1850,7 @@ static int jtag3_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AVRME } static int jtag3_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, - unsigned long addr, unsigned char * value) -{ + unsigned long addr, unsigned char * value) { unsigned char cmd[12]; unsigned char *resp, *cache_ptr = NULL; int status, unsupp = 0; @@ -1983,7 +1949,7 @@ static int jtag3_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM if (addr == 0) { if ((status = jtag3_command(pgm, cmd, 12, &resp, "read memory")) < 0) - return status; + return status; signature_cache[0] = resp[4]; signature_cache[1] = resp[5]; @@ -2054,8 +2020,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) -{ + unsigned long addr, unsigned char data) { unsigned char cmd[14]; unsigned char *resp; unsigned char *cache_ptr = 0; @@ -2139,7 +2104,7 @@ static int jtag3_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRME /* step #2: update our value in page cache, and copy * cache to mem->buf */ cache_ptr[addr & (pagesize - 1)] = data; - addr &= ~(pagesize - 1); /* page base address */ + addr &= ~(pagesize - 1); /* page base address */ memcpy(mem->buf + addr, cache_ptr, pagesize); /* step #3: write back */ i = jtag3_paged_write(pgm, p, mem, pagesize, addr, pagesize); @@ -2196,9 +2161,8 @@ static int jtag3_set_sck_period(const PROGRAMMER *pgm, double v) { * Read (an) emulator parameter(s). */ int jtag3_getparm(const PROGRAMMER *pgm, unsigned char scope, - unsigned char section, unsigned char parm, - unsigned char *value, unsigned char length) -{ + unsigned char section, unsigned char parm, + unsigned char *value, unsigned char length) { int status; unsigned char buf[6], *resp, c; char descr[60]; @@ -2213,7 +2177,7 @@ int jtag3_getparm(const PROGRAMMER *pgm, unsigned char scope, buf[5] = length; sprintf(descr, "get parameter (scope 0x%02x, section %d, parm %d)", - scope, section, parm); + scope, section, parm); if ((status = jtag3_command(pgm, buf, 6, &resp, descr)) < 0) return -1; @@ -2236,9 +2200,8 @@ int jtag3_getparm(const PROGRAMMER *pgm, unsigned char scope, * Write an emulator parameter. */ int jtag3_setparm(const PROGRAMMER *pgm, unsigned char scope, - unsigned char section, unsigned char parm, - unsigned char *value, unsigned char length) -{ + unsigned char section, unsigned char parm, + unsigned char *value, unsigned char length) { int status; unsigned char *buf, *resp; char descr[60]; @@ -2246,10 +2209,9 @@ int jtag3_setparm(const PROGRAMMER *pgm, unsigned char scope, pmsg_notice2("jtag3_setparm()\n"); sprintf(descr, "set parameter (scope 0x%02x, section %d, parm %d)", - scope, section, parm); + scope, section, parm); - if ((buf = malloc(6 + length)) == NULL) - { + if ((buf = malloc(6 + length)) == NULL) { pmsg_error("out of memory\n"); return -1; } @@ -2284,7 +2246,7 @@ int jtag3_read_sib(const PROGRAMMER *pgm, const AVRPART *p, char *sib) { u32_to_b4(cmd + 8, AVR_SIBLEN); if ((status = jtag3_command(pgm, cmd, 12, &resp, "read SIB")) < 0) - return status; + return status; memcpy(sib, resp+3, AVR_SIBLEN); sib[AVR_SIBLEN] = 0; // Zero terminate string @@ -2349,9 +2311,8 @@ static void jtag3_display(const PROGRAMMER *pgm, const char *p) { resp[status - 3] = 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], - (parms[3] | (parms[4] << 8))); + msg_info("%sICE FW version : %d.%02d (rel. %d)\n", p, parms[1], parms[2], + (parms[3] | (parms[4] << 8))); msg_info("%sSerial number : %s", p, resp); free(resp); } @@ -2363,7 +2324,7 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp) { if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_VTARGET, buf, 2) < 0) return; fmsg_out(fp, "%sVtarget %s: %.2f V\n", p, - verbose? "": " ", b2_to_u16(buf)/1000.0); + verbose? "": " ", b2_to_u16(buf)/1000.0); // Print features unique to the Power Debugger for(LNODEID ln=lfirst(pgm->id); ln; ln=lnext(ln)) { @@ -2375,7 +2336,7 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp) { return; analog_raw_data = b2_to_u16(buf); fmsg_out(fp, "%sVout set %s: %.2f V\n", p, - verbose? "": " ", analog_raw_data / 1000.0); + 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) @@ -2387,7 +2348,7 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp) { if (analog_raw_data & 0x0800) analog_raw_data |= 0xF000; fmsg_out(fp, "%sVout measured %s: %.02f V\n", p, - verbose? "": " ", ((float) analog_raw_data / -200.0)); + verbose? "": " ", ((float) analog_raw_data / -200.0)); } // Read channel A voltage @@ -2400,7 +2361,7 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp) { if (analog_raw_data & 0x0800) analog_raw_data |= 0xF000; fmsg_out(fp, "%sCh A voltage %s: %.03f V\n", p, - verbose? "": " ", ((float) analog_raw_data / -200.0)); + verbose? "": " ", ((float) analog_raw_data / -200.0)); } // Read channel A current @@ -2411,7 +2372,7 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp) { pmsg_error("invalid PARM3_ANALOG_A_CURRENT data packet format\n"); else fmsg_out(fp, "%sCh A current %s: %.3f mA\n", p, - verbose? "": " ", (float) analog_raw_data * 0.003472); + 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) @@ -2423,7 +2384,7 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp) { if (analog_raw_data & 0x0800) analog_raw_data |= 0xF000; fmsg_out(fp, "%sCh B voltage %s: %.03f V\n", p, - verbose? "": " ", (float) analog_raw_data / -200.0); + verbose? "": " ", (float) analog_raw_data / -200.0); } // Read channel B current @@ -2436,7 +2397,7 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp) { if (analog_raw_data & 0x0800) analog_raw_data |= 0xF000; fmsg_out(fp, "%sCh B current %s: %.3f mA\n", p, - verbose? "": " ", (float) analog_raw_data * 0.555556); + verbose? "": " ", (float) analog_raw_data * 0.555556); } break; } @@ -2622,8 +2583,7 @@ static void jtag3_disable_tpi(const PROGRAMMER *pgm) { } static int jtag3_read_byte_tpi(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, - unsigned long addr, unsigned char * value) -{ + unsigned long addr, unsigned char * value) { int result, pollidx; unsigned char buf[8]; unsigned long paddr = 0UL, *paddr_ptr = NULL; @@ -2634,11 +2594,10 @@ static int jtag3_read_byte_tpi(const PROGRAMMER *pgm, const AVRPART *p, const AV pmsg_notice2("jtag3_read_byte_tpi(.., %s, 0x%lx, ...)\n", mem->desc, addr); - buf[0] = XPRG_CMD_READ_MEM; if (strcmp(mem->desc, "lfuse") == 0 || - strcmp(mem->desc, "fuse") == 0) { + strcmp(mem->desc, "fuse") == 0) { buf[1] = XPRG_MEM_TYPE_FUSE; addr = 0; } else if (strcmp(mem->desc, "hfuse") == 0) { diff --git a/src/jtag3.h b/src/jtag3.h index beb1fc3d..157d4982 100644 --- a/src/jtag3.h +++ b/src/jtag3.h @@ -31,13 +31,13 @@ int jtag3_recv(const PROGRAMMER *pgm, unsigned char **msg); void jtag3_close(PROGRAMMER * pgm); int jtag3_getsync(const PROGRAMMER *pgm, int mode); int jtag3_getparm(const PROGRAMMER *pgm, unsigned char scope, - unsigned char section, unsigned char parm, - unsigned char *value, unsigned char length); + unsigned char section, unsigned char parm, + unsigned char *value, unsigned char length); int jtag3_setparm(const PROGRAMMER *pgm, unsigned char scope, - unsigned char section, unsigned char parm, - unsigned char *value, unsigned char length); + unsigned char section, unsigned char parm, + unsigned char *value, unsigned char length); 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_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp); int jtag3_set_vtarget(const PROGRAMMER *pgm, double voltage); extern const char jtag3_desc[]; From 3afdd550898e8152ff5088509fc2d5fbc1a2520c Mon Sep 17 00:00:00 2001 From: Jan Egil Ruud Date: Tue, 22 Nov 2022 13:23:57 +0100 Subject: [PATCH 03/22] Get rid of TPI magic numbers. --- src/jtag3.c | 4 ++-- src/jtag3_private.h | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/jtag3.c b/src/jtag3.c index b2809983..71eeea76 100644 --- a/src/jtag3.c +++ b/src/jtag3.c @@ -2542,7 +2542,7 @@ static int jtag3_initialize_tpi(const PROGRAMMER *pgm, const AVRPART *p) { cmdbuf[0] = XPRG_CMD_SET_PARAM; cmdbuf[1] = XPRG_PARAM_NVMCMD_ADDR; - cmdbuf[2] = 0x33; // NVMCMD address + cmdbuf[2] = TPI_NVMCMD_ADDRESS; if (jtag3_send_tpi(pgm, cmdbuf, 3) < 0) { pmsg_error("Set NVMCMD address failed\n"); @@ -2553,7 +2553,7 @@ static int jtag3_initialize_tpi(const PROGRAMMER *pgm, const AVRPART *p) { cmdbuf[0] = XPRG_CMD_SET_PARAM; cmdbuf[1] = XPRG_PARAM_NVMCSR_ADDR; - cmdbuf[2] = 0x32; // NVMCSR address + cmdbuf[2] = TPI_NVMCSR_ADDRESS; if (jtag3_send_tpi(pgm, cmdbuf, 3) < 0) { pmsg_error("Set NVMCSR address failed\n"); diff --git a/src/jtag3_private.h b/src/jtag3_private.h index a1555117..2e971729 100644 --- a/src/jtag3_private.h +++ b/src/jtag3_private.h @@ -365,6 +365,9 @@ #define XPRG_PARAM_NVMCMD_ADDR 0x03 #define XPRG_PARAM_NVMCSR_ADDR 0x04 +#define TPI_NVMCMD_ADDRESS 0x33 +#define TPI_NVMCSR_ADDRESS 0x32 + #if !defined(JTAG3_PRIVATE_EXPORTED) From 5dc2545716fab73fe9d7520b24375dc375beb441 Mon Sep 17 00:00:00 2001 From: Jan Egil Ruud Date: Tue, 22 Nov 2022 14:05:01 +0100 Subject: [PATCH 04/22] Cleaned and improved TPI send and receive. --- src/jtag3.c | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/src/jtag3.c b/src/jtag3.c index 71eeea76..1eab5204 100644 --- a/src/jtag3.c +++ b/src/jtag3.c @@ -165,6 +165,22 @@ u16_to_b2(unsigned char *b, unsigned short l) b[1] = (l >> 8) & 0xff; } +static void +u32_to_b4_big_endian(unsigned char *b, unsigned long l) +{ + b[0] = (l >> 24) & 0xff; + b[1] = (l >> 16) & 0xff; + b[2] = (l >> 8) & 0xff; + b[3] = l & 0xff; +} + +static void +u16_to_b2_big_endian(unsigned char *b, unsigned short l) +{ + b[0] = (l >> 8) & 0xff; + b[1] = l & 0xff; +} + static bool matches(const char *s, const char *pat) { return strncmp(s, pat, strlen(pat)) == 0; @@ -2491,7 +2507,7 @@ static int jtag3_send_tpi(const PROGRAMMER *pgm, unsigned char *data, size_t len memcpy(cmdbuf + 1, data, len); msg_trace("STK500V2: jtag3_send_tpi("); - for (size_t i=0; idesc, "lock") == 0) { buf[1] = XPRG_MEM_TYPE_LOCKBITS; - paddr = 0x3F00 + addr; + paddr = mem->offset + addr; } else if (strcmp(mem->desc, "calibration") == 0) { buf[1] = XPRG_MEM_TYPE_LOCKBITS; - paddr = 0x3F80 + addr; + paddr = mem->offset + addr; } else if (strcmp(mem->desc, "signature") == 0) { buf[1] = XPRG_MEM_TYPE_LOCKBITS; - paddr = 0x3FC0 + addr; + paddr = mem->offset + addr; } - buf[2] = (paddr>>24) & 0xFF; - buf[3] = (paddr>>16) & 0xFF; - buf[4] = (paddr>>8) & 0xFF; - buf[5] = paddr & 0xFF; - - buf[6] = 0; // Length MSB - buf[7] = 1; // Length LSB, 1 since we are reading only one byte + u32_to_b4_big_endian((buf+2), paddr); // Address + u16_to_b2_big_endian((buf+6), 1); // Size if (jtag3_send_tpi(pgm, buf, len) < 0) return -1; From f9a2bd0327da226ee466b1ab273e24f975c92f91 Mon Sep 17 00:00:00 2001 From: Jan Egil Ruud Date: Wed, 23 Nov 2022 14:25:14 +0100 Subject: [PATCH 05/22] Got added support for reading and writing fuses, and chiperase. --- src/jtag3.c | 153 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 120 insertions(+), 33 deletions(-) diff --git a/src/jtag3.c b/src/jtag3.c index 1eab5204..79c34e75 100644 --- a/src/jtag3.c +++ b/src/jtag3.c @@ -2491,6 +2491,27 @@ static unsigned int jtag3_memaddr(const PROGRAMMER *pgm, const AVRPART *p, const return addr; } +unsigned char tpi_get_memtype(const AVRMEM *mem) { + unsigned char memtype; + if (strcmp(mem->desc, "fuse") == 0) { + memtype = XPRG_MEM_TYPE_FUSE; + } else if (strcmp(mem->desc, "lock") == 0) { + memtype = XPRG_MEM_TYPE_LOCKBITS; + } else if (strcmp(mem->desc, "calibration") == 0) { + memtype = XPRG_MEM_TYPE_LOCKBITS; + } else if (strcmp(mem->desc, "signature") == 0) { + memtype = XPRG_MEM_TYPE_LOCKBITS; + } + else { + memtype = XPRG_MEM_TYPE_APPL; + } + return memtype; +} + +// void tpi_print_error_status(unsigned char error) { +// pmsg_error("error communicating with programmer, received status 0x%02x\n", error); +// } + /* * Send the data as a JTAGICE3 encapsulated TPI packet. */ @@ -2588,7 +2609,6 @@ static void jtag3_enable_tpi(PROGRAMMER *pgm, const AVRPART *p) { static void jtag3_disable_tpi(const PROGRAMMER *pgm) { unsigned char cmdbuf[4]; - int result; cmdbuf[0] = XPRG_CMD_LEAVE_PROGMODE; @@ -2601,39 +2621,17 @@ static void jtag3_disable_tpi(const PROGRAMMER *pgm) { static int jtag3_read_byte_tpi(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, unsigned long addr, unsigned char * value) { - int result, pollidx; - unsigned char buf[8]; - unsigned long paddr = 0UL, *paddr_ptr = NULL; - unsigned int pagesize = 0; - unsigned char *cache_ptr = NULL; - OPCODE *op; + int result; size_t len = 8; + unsigned char buf[len]; + unsigned long paddr = 0UL; pmsg_notice2("jtag3_read_byte_tpi(.., %s, 0x%lx, ...)\n", mem->desc, addr); + paddr = mem->offset + addr; + buf[0] = XPRG_CMD_READ_MEM; - - if (strcmp(mem->desc, "lfuse") == 0 || - strcmp(mem->desc, "fuse") == 0) { - buf[1] = XPRG_MEM_TYPE_FUSE; - addr = 0; - } else if (strcmp(mem->desc, "hfuse") == 0) { - buf[1] = XPRG_MEM_TYPE_FUSE; - addr = 1; - } else if (strcmp(mem->desc, "efuse") == 0) { - buf[1] = XPRG_MEM_TYPE_FUSE; - addr = 2; - } else if (strcmp(mem->desc, "lock") == 0) { - buf[1] = XPRG_MEM_TYPE_LOCKBITS; - paddr = mem->offset + addr; - } else if (strcmp(mem->desc, "calibration") == 0) { - buf[1] = XPRG_MEM_TYPE_LOCKBITS; - paddr = mem->offset + addr; - } else if (strcmp(mem->desc, "signature") == 0) { - buf[1] = XPRG_MEM_TYPE_LOCKBITS; - paddr = mem->offset + addr; - } - + buf[1] = tpi_get_memtype(mem); u32_to_b4_big_endian((buf+2), paddr); // Address u16_to_b2_big_endian((buf+6), 1); // Size @@ -2642,16 +2640,105 @@ static int jtag3_read_byte_tpi(const PROGRAMMER *pgm, const AVRPART *p, const AV result = jtag3_recv_tpi(pgm, buf); if (result < 0) { - pmsg_error("timeout/error communicating with programmer\n"); + pmsg_error("error in communication, received status 0x%02x\n", result); return -1; } *value = buf[2]; return 0; } +static int jtag3_erase_tpi(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, + unsigned long addr) { + size_t len = 6; + unsigned char buf[len]; + int result; + unsigned long paddr = 0UL; + + buf[0] = XPRG_CMD_ERASE; + if (strcmp(mem->desc, "fuse") == 0) { + buf[1] = XPRG_ERASE_CONFIG; + } else if (strcmp(mem->desc, "flash") == 0) { + buf[1] = XPRG_ERASE_APP; + } else { + pmsg_error("jtag3_erase_tpi() unsupported memory: %s\n", mem->desc); + return -1; + } + paddr = (mem->offset + addr) | 0x01; // An erase is triggered by an access to the hi-byte + u32_to_b4_big_endian((buf+2), paddr); + + if (jtag3_send_tpi(pgm, buf, len) < 0) + return -1; + + result = jtag3_recv_tpi(pgm, buf); + if (result < 0) { + pmsg_error("error in communication, received status 0x%02x\n", result); + return -1; + } + return 0; +} + +static int jtag3_write_byte_tpi(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, + unsigned long addr, unsigned char data) { + size_t len = 11; + unsigned char buf[len]; + int result; + unsigned long paddr = 0UL; + + result = jtag3_erase_tpi(pgm, p, mem, addr); + if (result < 0) { + pmsg_error("error in communication, received status 0x%02x\n", result); + return -1; + } + + paddr = mem->offset + addr; + + buf[0] = XPRG_CMD_WRITE_MEM; + buf[1] = tpi_get_memtype(mem); + buf[2] = 0; // Page Mode - Not used + u32_to_b4_big_endian((buf+3), paddr); // Address + u16_to_b2_big_endian((buf+7), 2); // Size + buf[9] = data; + buf[10] = 0x00; + + if (jtag3_send_tpi(pgm, buf, len) < 0) + return -1; + + result = jtag3_recv_tpi(pgm, buf); + if (result < 0) { + pmsg_error("error in communication, received status 0x%02x\n", result); + return -1; + } + return 0; +} + static int jtag3_chip_erase_tpi(const PROGRAMMER *pgm, const AVRPART *p) { - pmsg_error("jtag3_chip_erase_tpi() not implemented\n"); - return -1; + size_t len = 6; + unsigned char buf[len]; + int result; + unsigned long paddr = 0UL; + + AVRMEM *m = avr_locate_mem(p, "flash"); + if (m == NULL) { + pmsg_error("no flash memory for part %s\n", p->desc); + return LIBAVRDUDE_GENERAL_FAILURE; + } + + paddr = m->offset | 0x01; + + buf[0] = XPRG_CMD_ERASE; + buf[1] = XPRG_ERASE_CHIP; + // An erase is triggered by an access to the hi-byte + u32_to_b4_big_endian((buf+2), paddr); + + if (jtag3_send_tpi(pgm, buf, len) < 0) + return -1; + + result = jtag3_recv_tpi(pgm, buf); + if (result < 0) { + pmsg_error("error in communication, received status 0x%02x\n", result); + return -1; + } + return 0; } static int jtag3_open_tpi(PROGRAMMER *pgm, const char *port) { @@ -2847,7 +2934,7 @@ void jtag3_tpi_initpgm(PROGRAMMER *pgm) { pgm->open = jtag3_open_tpi; pgm->close = jtag3_close_tpi; pgm->read_byte = jtag3_read_byte_tpi; - pgm->write_byte = jtag3_write_byte; + pgm->write_byte = jtag3_write_byte_tpi; /* * optional functions From f2156b834d6f23dfbbe204b953b2e86985c83739 Mon Sep 17 00:00:00 2001 From: Jan Egil Ruud Date: Tue, 29 Nov 2022 09:52:45 +0100 Subject: [PATCH 06/22] #822 Added sigrow memory to tiny102 and tiny 104, and removed duplicate lockbits. --- src/avrdude.conf.in | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/avrdude.conf.in b/src/avrdude.conf.in index af51d3dc..d96a31b8 100644 --- a/src/avrdude.conf.in +++ b/src/avrdude.conf.in @@ -13265,12 +13265,6 @@ part offset = 0x3f00; ; - memory "lockbits" - size = 1; - page_size = 16; - offset = 0x3f00; - ; - memory "signature" size = 3; page_size = 16; @@ -13402,6 +13396,12 @@ part parent ".reduced_core_tiny" offset = 0x4000; blocksize = 128; ; + + memory "sigrow" + size = 16; + page_size = 16; + offset = 0x3fc6; + ; ; #------------------------------------------------------------ @@ -13420,6 +13420,12 @@ part parent ".reduced_core_tiny" offset = 0x4000; blocksize = 128; ; + + memory "sigrow" + size = 16; + page_size = 16; + offset = 0x3fc6; + ; ; #------------------------------------------------------------ From 2f5566a8edde8c5073d8a85e2fdfe2876ac4c780 Mon Sep 17 00:00:00 2001 From: Jan Egil Ruud Date: Tue, 29 Nov 2022 20:34:05 +0100 Subject: [PATCH 07/22] #822 Added support for TPI page load. --- src/jtag3.c | 149 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 119 insertions(+), 30 deletions(-) diff --git a/src/jtag3.c b/src/jtag3.c index 79c34e75..ddddedd9 100644 --- a/src/jtag3.c +++ b/src/jtag3.c @@ -2501,8 +2501,9 @@ unsigned char tpi_get_memtype(const AVRMEM *mem) { memtype = XPRG_MEM_TYPE_LOCKBITS; } else if (strcmp(mem->desc, "signature") == 0) { memtype = XPRG_MEM_TYPE_LOCKBITS; - } - else { + } else if (strcmp(mem->desc, "sigrow") == 0) { + memtype = XPRG_MEM_TYPE_LOCKBITS; + } else { memtype = XPRG_MEM_TYPE_APPL; } return memtype; @@ -2520,17 +2521,17 @@ static int jtag3_send_tpi(const PROGRAMMER *pgm, unsigned char *data, size_t len int rv; if ((cmdbuf = malloc(len + 1)) == NULL) { - pmsg_error("out of memory for command packet\n"); + pmsg_error("jtag3_send_tpi(): out of memory for command packet\n"); exit(1); } cmdbuf[0] = SCOPE_AVR_TPI; memcpy(cmdbuf + 1, data, len); - msg_trace("STK500V2: jtag3_send_tpi("); + msg_trace("[TPI send] "); for (size_t i=1; i<=len; i++) msg_trace("0x%02x ", cmdbuf[i]); - msg_trace(", %d)\n", (int) len); + msg_trace("\n"); rv = jtag3_send(pgm, cmdbuf, len + 1); free(cmdbuf); @@ -2538,26 +2539,24 @@ static int jtag3_send_tpi(const PROGRAMMER *pgm, unsigned char *data, size_t len return rv; } -int jtag3_recv_tpi(const PROGRAMMER *pgm, unsigned char *resp) { +int jtag3_recv_tpi(const PROGRAMMER *pgm, unsigned char **msg) { int rv; - unsigned char *tpimsg; - rv = jtag3_recv(pgm, &tpimsg); + rv = jtag3_recv(pgm, msg); if (rv <= 0) { - pmsg_error("unable to receive\n"); + pmsg_error("jtag3_recv_tpi(): unable to receive\n"); return -1; } rv = rv - 1; - memcpy(resp, tpimsg + 1, rv); - free(tpimsg); + memcpy(*msg, *msg + 1, rv); - msg_trace("STK500V2: jtag3_recv_tpi("); + msg_trace("[TPI recv] "); for (size_t i=0; idesc, addr); @@ -2638,19 +2669,21 @@ static int jtag3_read_byte_tpi(const PROGRAMMER *pgm, const AVRPART *p, const AV if (jtag3_send_tpi(pgm, buf, len) < 0) return -1; - result = jtag3_recv_tpi(pgm, buf); + result = jtag3_recv_tpi(pgm, &resp); if (result < 0) { pmsg_error("error in communication, received status 0x%02x\n", result); return -1; } - *value = buf[2]; + *value = resp[2]; + free(resp); return 0; } static int jtag3_erase_tpi(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, - unsigned long addr) { - size_t len = 6; + unsigned long addr) { + static size_t len = 6; unsigned char buf[len]; + unsigned char* resp; int result; unsigned long paddr = 0UL; @@ -2663,17 +2696,18 @@ static int jtag3_erase_tpi(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM pmsg_error("jtag3_erase_tpi() unsupported memory: %s\n", mem->desc); return -1; } - paddr = (mem->offset + addr) | 0x01; // An erase is triggered by an access to the hi-byte + paddr = (mem->offset + addr) | 0x01; // An erase is triggered by an access to the hi-byte u32_to_b4_big_endian((buf+2), paddr); if (jtag3_send_tpi(pgm, buf, len) < 0) return -1; - result = jtag3_recv_tpi(pgm, buf); + result = jtag3_recv_tpi(pgm, &resp); if (result < 0) { pmsg_error("error in communication, received status 0x%02x\n", result); return -1; } + free(resp); return 0; } @@ -2681,6 +2715,7 @@ static int jtag3_write_byte_tpi(const PROGRAMMER *pgm, const AVRPART *p, const A unsigned long addr, unsigned char data) { size_t len = 11; unsigned char buf[len]; + unsigned char* resp; int result; unsigned long paddr = 0UL; @@ -2703,17 +2738,19 @@ static int jtag3_write_byte_tpi(const PROGRAMMER *pgm, const AVRPART *p, const A if (jtag3_send_tpi(pgm, buf, len) < 0) return -1; - result = jtag3_recv_tpi(pgm, buf); + result = jtag3_recv_tpi(pgm, &resp); if (result < 0) { pmsg_error("error in communication, received status 0x%02x\n", result); return -1; } + free(resp); return 0; } static int jtag3_chip_erase_tpi(const PROGRAMMER *pgm, const AVRPART *p) { size_t len = 6; unsigned char buf[len]; + unsigned char* resp; int result; unsigned long paddr = 0UL; @@ -2733,11 +2770,12 @@ static int jtag3_chip_erase_tpi(const PROGRAMMER *pgm, const AVRPART *p) { if (jtag3_send_tpi(pgm, buf, len) < 0) return -1; - result = jtag3_recv_tpi(pgm, buf); + result = jtag3_recv_tpi(pgm, &resp); if (result < 0) { pmsg_error("error in communication, received status 0x%02x\n", result); return -1; } + free(resp); return 0; } @@ -2753,6 +2791,57 @@ void jtag3_close_tpi(PROGRAMMER *pgm) { pmsg_notice2("jtag3_close_tpi() is empty. No action necessary.\n"); } +static int jtag3_paged_load_tpi(const PROGRAMMER *pgm, const AVRPART *p, + const AVRMEM *m, unsigned int page_size, + unsigned int addr, unsigned int n_bytes) { + unsigned int block_size = 0; + unsigned int maxaddr = addr + n_bytes; + unsigned char cmd[8]; + unsigned char *resp; + int status; + long otimeout = serial_recv_timeout; + + pmsg_notice2("jtag3_paged_load_tpi(.., %s, %d, 0x%04x, %d)\n", + m->desc, page_size, addr, n_bytes); + + if(m->offset) + msg_notice2(" mapped to address: 0x%04x\n", (addr+m->offset)); + + cmd[0] = XPRG_CMD_READ_MEM; + cmd[1] = tpi_get_memtype(m); + + if(m->blocksize > page_size) + page_size = m->blocksize; + + serial_recv_timeout = 100; + for (; addr < maxaddr; addr += page_size) { + if ((maxaddr - addr) < page_size) + block_size = maxaddr - addr; + else + block_size = page_size; + pmsg_debug("jtag3_paged_load_tpi(): " + "block_size at addr 0x%x is %d\n", addr, block_size); + + u32_to_b4_big_endian((cmd+2), addr + m->offset); // Address + u16_to_b2_big_endian((cmd+6), block_size); // Size + + if ((status = jtag3_command_tpi(pgm, cmd, 8, &resp, "read memory")) < 0) + return -1; + + if (resp[1] != XPRG_ERR_OK || + status < block_size + 2) { + pmsg_error("wrong/short reply to read memory command\n"); + serial_recv_timeout = otimeout; + free(resp); + return -1; + } + memcpy(m->buf + addr, resp + 2, status - 2); + free(resp); + } + serial_recv_timeout = otimeout; + + return n_bytes; +} const char jtag3_desc[] = "Atmel JTAGICE3"; @@ -2940,7 +3029,7 @@ void jtag3_tpi_initpgm(PROGRAMMER *pgm) { * optional functions */ pgm->paged_write = jtag3_paged_write; - pgm->paged_load = jtag3_paged_load; + pgm->paged_load = jtag3_paged_load_tpi; pgm->print_parms = jtag3_print_parms; pgm->setup = jtag3_setup; pgm->teardown = jtag3_teardown; From 90bd24a9021c66767b1039ad04a316793c5f920e Mon Sep 17 00:00:00 2001 From: Jan Egil Ruud Date: Wed, 30 Nov 2022 00:14:19 +0100 Subject: [PATCH 08/22] #822 Added support for TPI page write. --- src/jtag3.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 71 insertions(+), 5 deletions(-) diff --git a/src/jtag3.c b/src/jtag3.c index ddddedd9..e267d484 100644 --- a/src/jtag3.c +++ b/src/jtag3.c @@ -2652,7 +2652,7 @@ static void jtag3_disable_tpi(const PROGRAMMER *pgm) { static int jtag3_read_byte_tpi(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, unsigned long addr, unsigned char * value) { int result; - static size_t len = 8; + const size_t len = 8; unsigned char buf[len]; unsigned char* resp; unsigned long paddr = 0UL; @@ -2681,7 +2681,7 @@ static int jtag3_read_byte_tpi(const PROGRAMMER *pgm, const AVRPART *p, const AV static int jtag3_erase_tpi(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, unsigned long addr) { - static size_t len = 6; + const size_t len = 6; unsigned char buf[len]; unsigned char* resp; int result; @@ -2713,7 +2713,7 @@ static int jtag3_erase_tpi(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM static int jtag3_write_byte_tpi(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, unsigned long addr, unsigned char data) { - size_t len = 11; + const size_t len = 11; unsigned char buf[len]; unsigned char* resp; int result; @@ -2748,7 +2748,7 @@ static int jtag3_write_byte_tpi(const PROGRAMMER *pgm, const AVRPART *p, const A } static int jtag3_chip_erase_tpi(const PROGRAMMER *pgm, const AVRPART *p) { - size_t len = 6; + const size_t len = 6; unsigned char buf[len]; unsigned char* resp; int result; @@ -2801,6 +2801,7 @@ static int jtag3_paged_load_tpi(const PROGRAMMER *pgm, const AVRPART *p, int status; long otimeout = serial_recv_timeout; + msg_notice2("\n"); pmsg_notice2("jtag3_paged_load_tpi(.., %s, %d, 0x%04x, %d)\n", m->desc, page_size, addr, n_bytes); @@ -2843,6 +2844,71 @@ static int jtag3_paged_load_tpi(const PROGRAMMER *pgm, const AVRPART *p, return n_bytes; } +static int jtag3_paged_write_tpi(const PROGRAMMER *pgm, const AVRPART *p, + const AVRMEM *m, unsigned int page_size, + unsigned int addr, unsigned int n_bytes) { + unsigned int block_size; + unsigned int maxaddr = addr + n_bytes; + unsigned char *cmd; + unsigned char *resp; + int status; + long otimeout = serial_recv_timeout; + + msg_notice2("\n"); + pmsg_notice2("jtag3_paged_write_tpi(.., %s, %d, 0x%04x, %d)\n", m->desc, page_size, addr, n_bytes); + + if(m->offset) + msg_notice2(" mapped to address: 0x%04x\n", (addr+m->offset)); + + if (page_size == 0) + page_size = m->page_size; + + if ((cmd = malloc(page_size + 9)) == NULL) { + pmsg_error("out of memory\n"); + return -1; + } + + cmd[0] = XPRG_CMD_WRITE_MEM; + cmd[1] = tpi_get_memtype(m); + cmd[2] = 0; // Page Mode; Not used - ignored + + serial_recv_timeout = 100; + for (; addr < maxaddr; addr += page_size) { + if ((maxaddr - addr) < page_size) + block_size = maxaddr - addr; + else + block_size = page_size; + pmsg_debug("jtag3_paged_write(): " + "block_size at addr 0x%x is %d\n", addr, block_size); + + u32_to_b4_big_endian((cmd+3), addr + m->offset); // Address + u16_to_b2_big_endian((cmd+7), page_size); // Size + + /* + * If a partial page has been requested, set the remainder to 0xff. + * (Maybe we should rather read back the existing contents instead + * before? Doesn't matter much, as bits cannot be written to 1 anyway.) + */ + memset(cmd + 9, 0xff, page_size); + memcpy(cmd + 9, m->buf + addr, block_size); + + if ((status = jtag3_command_tpi(pgm, cmd, page_size + 9, + &resp, "write memory")) < 0) { + free(cmd); + serial_recv_timeout = otimeout; + return -1; + } + + free(resp); + } + + free(cmd); + serial_recv_timeout = otimeout; + + return n_bytes; +} + + const char jtag3_desc[] = "Atmel JTAGICE3"; void jtag3_initpgm(PROGRAMMER *pgm) { @@ -3028,7 +3094,7 @@ void jtag3_tpi_initpgm(PROGRAMMER *pgm) { /* * optional functions */ - pgm->paged_write = jtag3_paged_write; + pgm->paged_write = jtag3_paged_write_tpi; pgm->paged_load = jtag3_paged_load_tpi; pgm->print_parms = jtag3_print_parms; pgm->setup = jtag3_setup; From cad296f780fa3bf364d7f4848f2bb18e32638056 Mon Sep 17 00:00:00 2001 From: Jan Egil Ruud Date: Wed, 30 Nov 2022 00:27:25 +0100 Subject: [PATCH 09/22] Attempt to fix msvc builds. --- src/jtag3.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/jtag3.c b/src/jtag3.c index e267d484..5d287def 100644 --- a/src/jtag3.c +++ b/src/jtag3.c @@ -2653,7 +2653,7 @@ static int jtag3_read_byte_tpi(const PROGRAMMER *pgm, const AVRPART *p, const AV unsigned long addr, unsigned char * value) { int result; const size_t len = 8; - unsigned char buf[len]; + unsigned char buf[8]; // Using "len" as array length causes msvc build jobs to fail with error C2057: expected constant expression unsigned char* resp; unsigned long paddr = 0UL; @@ -2682,7 +2682,7 @@ static int jtag3_read_byte_tpi(const PROGRAMMER *pgm, const AVRPART *p, const AV static int jtag3_erase_tpi(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, unsigned long addr) { const size_t len = 6; - unsigned char buf[len]; + unsigned char buf[6]; // Using "len" as array length causes msvc build jobs to fail with error C2057: expected constant expression unsigned char* resp; int result; unsigned long paddr = 0UL; @@ -2714,7 +2714,7 @@ static int jtag3_erase_tpi(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM static int jtag3_write_byte_tpi(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, unsigned long addr, unsigned char data) { const size_t len = 11; - unsigned char buf[len]; + unsigned char buf[11]; // Using "len" as array length causes msvc build jobs to fail with error C2057: expected constant expression unsigned char* resp; int result; unsigned long paddr = 0UL; @@ -2733,7 +2733,7 @@ static int jtag3_write_byte_tpi(const PROGRAMMER *pgm, const AVRPART *p, const A u32_to_b4_big_endian((buf+3), paddr); // Address u16_to_b2_big_endian((buf+7), 2); // Size buf[9] = data; - buf[10] = 0x00; + buf[10] = 0xFF; if (jtag3_send_tpi(pgm, buf, len) < 0) return -1; @@ -2749,7 +2749,7 @@ static int jtag3_write_byte_tpi(const PROGRAMMER *pgm, const AVRPART *p, const A static int jtag3_chip_erase_tpi(const PROGRAMMER *pgm, const AVRPART *p) { const size_t len = 6; - unsigned char buf[len]; + unsigned char buf[6]; // Using "len" as array length causes msvc build jobs to fail with error C2057: expected constant expression unsigned char* resp; int result; unsigned long paddr = 0UL; From 1eb6a060558645507561fb2e768847088d29915c Mon Sep 17 00:00:00 2001 From: Jan Egil Ruud Date: Wed, 30 Nov 2022 23:07:05 +0100 Subject: [PATCH 10/22] #822 Small refactoring and clean up. --- src/jtag3.c | 200 +++++++++++++++++++++++----------------------------- 1 file changed, 88 insertions(+), 112 deletions(-) diff --git a/src/jtag3.c b/src/jtag3.c index 5d287def..d53ba15e 100644 --- a/src/jtag3.c +++ b/src/jtag3.c @@ -2559,52 +2559,6 @@ int jtag3_recv_tpi(const PROGRAMMER *pgm, unsigned char **msg) { return rv; } -/* - * initialize the AVR device and prepare it to accept commands - */ -static int jtag3_initialize_tpi(const PROGRAMMER *pgm, const AVRPART *p) { - unsigned char cmdbuf[4]; - unsigned char* resp; - // AVRMEM * m; - pmsg_info("jtag3_initialize_tpi() start\n"); - - cmdbuf[0] = XPRG_CMD_ENTER_PROGMODE; - - if (jtag3_send_tpi(pgm, cmdbuf, 1) < 0) { - pmsg_error("XPRG_CMD_ENTER_PROGMODE failed\n"); - return -1; - } - - jtag3_recv_tpi(pgm, &resp); - free(resp); - - cmdbuf[0] = XPRG_CMD_SET_PARAM; - cmdbuf[1] = XPRG_PARAM_NVMCMD_ADDR; - cmdbuf[2] = TPI_NVMCMD_ADDRESS; - - if (jtag3_send_tpi(pgm, cmdbuf, 3) < 0) { - pmsg_error("Set NVMCMD address failed\n"); - return -1; - } - - jtag3_recv_tpi(pgm, &resp); - free(resp); - - cmdbuf[0] = XPRG_CMD_SET_PARAM; - cmdbuf[1] = XPRG_PARAM_NVMCSR_ADDR; - cmdbuf[2] = TPI_NVMCSR_ADDRESS; - - if (jtag3_send_tpi(pgm, cmdbuf, 3) < 0) { - pmsg_error("Set NVMCSR address failed\n"); - return -1; - } - - jtag3_recv_tpi(pgm, &resp); - free(resp); - - return 0; -} - int jtag3_command_tpi(const PROGRAMMER *pgm, unsigned char *cmd, unsigned int cmdlen, unsigned char **resp, const char *descr) { int status; @@ -2621,7 +2575,7 @@ int jtag3_command_tpi(const PROGRAMMER *pgm, unsigned char *cmd, unsigned int cm c = (*resp)[1]; if (c != XPRG_ERR_OK) { - pmsg_notice("bad response to %s command: 0x%02x\n", descr, c); + pmsg_error("[TPI] command %s FAILED! Status: 0x%02x\n", descr, c); status = (*resp)[3]; free(*resp); resp = 0; @@ -2631,49 +2585,76 @@ int jtag3_command_tpi(const PROGRAMMER *pgm, unsigned char *cmd, unsigned int cm return status; } +/* + * initialize the AVR device and prepare it to accept commands + */ +static int jtag3_initialize_tpi(const PROGRAMMER *pgm, const AVRPART *p) { + unsigned char cmd[4]; + unsigned char* resp; + int status; + + pmsg_info("jtag3_initialize_tpi() start\n"); + + cmd[0] = XPRG_CMD_ENTER_PROGMODE; + + if ((status = jtag3_command_tpi(pgm, cmd, 1, &resp, "Enter Progmode")) < 0) + return -1; + free(resp); + + cmd[0] = XPRG_CMD_SET_PARAM; + cmd[1] = XPRG_PARAM_NVMCMD_ADDR; + cmd[2] = TPI_NVMCMD_ADDRESS; + + if ((status = jtag3_command_tpi(pgm, cmd, 3, &resp, "Set NVMCMD")) < 0) + return -1; + free(resp); + + cmd[0] = XPRG_CMD_SET_PARAM; + cmd[1] = XPRG_PARAM_NVMCSR_ADDR; + cmd[2] = TPI_NVMCSR_ADDRESS; + + if ((status = jtag3_command_tpi(pgm, cmd, 3, &resp, "Set NVMCSR")) < 0) + return -1; + free(resp); + return 0; +} + static void jtag3_enable_tpi(PROGRAMMER *pgm, const AVRPART *p) { pmsg_notice2("jtag3_enable_tpi() is empty. No action necessary.\n"); } static void jtag3_disable_tpi(const PROGRAMMER *pgm) { - unsigned char cmdbuf[4]; + unsigned char cmd[1]; unsigned char* resp; + int status; - cmdbuf[0] = XPRG_CMD_LEAVE_PROGMODE; + cmd[0] = XPRG_CMD_LEAVE_PROGMODE; - if (jtag3_send_tpi(pgm, cmdbuf, 1) < 0) { - pmsg_error("XPRG_CMD_LEAVE_PROGMODE failed\n"); + if ((status = jtag3_command_tpi(pgm, cmd, 1, &resp, "Leave Progmode")) < 0) return; - } - jtag3_recv_tpi(pgm, &resp); free(resp); } static int jtag3_read_byte_tpi(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, unsigned long addr, unsigned char * value) { - int result; + int status; const size_t len = 8; - unsigned char buf[8]; // Using "len" as array length causes msvc build jobs to fail with error C2057: expected constant expression + unsigned char cmd[8]; // Using "len" as array length causes msvc build jobs to fail with error C2057: expected constant expression unsigned char* resp; unsigned long paddr = 0UL; + msg_notice2("\n"); pmsg_notice2("jtag3_read_byte_tpi(.., %s, 0x%lx, ...)\n", mem->desc, addr); paddr = mem->offset + addr; - buf[0] = XPRG_CMD_READ_MEM; - buf[1] = tpi_get_memtype(mem); - u32_to_b4_big_endian((buf+2), paddr); // Address - u16_to_b2_big_endian((buf+6), 1); // Size + cmd[0] = XPRG_CMD_READ_MEM; + cmd[1] = tpi_get_memtype(mem); + u32_to_b4_big_endian((cmd+2), paddr); // Address + u16_to_b2_big_endian((cmd+6), 1); // Size - if (jtag3_send_tpi(pgm, buf, len) < 0) + if ((status = jtag3_command_tpi(pgm, cmd, len, &resp, "read byte")) < 0) return -1; - - result = jtag3_recv_tpi(pgm, &resp); - if (result < 0) { - pmsg_error("error in communication, received status 0x%02x\n", result); - return -1; - } *value = resp[2]; free(resp); return 0; @@ -2682,76 +2663,77 @@ static int jtag3_read_byte_tpi(const PROGRAMMER *pgm, const AVRPART *p, const AV static int jtag3_erase_tpi(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, unsigned long addr) { const size_t len = 6; - unsigned char buf[6]; // Using "len" as array length causes msvc build jobs to fail with error C2057: expected constant expression + unsigned char cmd[6]; // Using "len" as array length causes msvc build jobs to fail with error C2057: expected constant expression unsigned char* resp; - int result; + int status; unsigned long paddr = 0UL; - buf[0] = XPRG_CMD_ERASE; + cmd[0] = XPRG_CMD_ERASE; if (strcmp(mem->desc, "fuse") == 0) { - buf[1] = XPRG_ERASE_CONFIG; + cmd[1] = XPRG_ERASE_CONFIG; } else if (strcmp(mem->desc, "flash") == 0) { - buf[1] = XPRG_ERASE_APP; + cmd[1] = XPRG_ERASE_APP; } else { pmsg_error("jtag3_erase_tpi() unsupported memory: %s\n", mem->desc); return -1; } paddr = (mem->offset + addr) | 0x01; // An erase is triggered by an access to the hi-byte - u32_to_b4_big_endian((buf+2), paddr); + u32_to_b4_big_endian((cmd+2), paddr); - if (jtag3_send_tpi(pgm, buf, len) < 0) + if ((status = jtag3_command_tpi(pgm, cmd, len, &resp, "erase")) < 0) return -1; - - result = jtag3_recv_tpi(pgm, &resp); - if (result < 0) { - pmsg_error("error in communication, received status 0x%02x\n", result); - return -1; - } free(resp); return 0; } static int jtag3_write_byte_tpi(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, unsigned long addr, unsigned char data) { - const size_t len = 11; - unsigned char buf[11]; // Using "len" as array length causes msvc build jobs to fail with error C2057: expected constant expression + size_t len = 11; + unsigned char cmd[17]; unsigned char* resp; - int result; + int status; unsigned long paddr = 0UL; - result = jtag3_erase_tpi(pgm, p, mem, addr); - if (result < 0) { - pmsg_error("error in communication, received status 0x%02x\n", result); + status = jtag3_erase_tpi(pgm, p, mem, addr); + if (status < 0) { + pmsg_error("error in communication, received status 0x%02x\n", status); return -1; } paddr = mem->offset + addr; - buf[0] = XPRG_CMD_WRITE_MEM; - buf[1] = tpi_get_memtype(mem); - buf[2] = 0; // Page Mode - Not used - u32_to_b4_big_endian((buf+3), paddr); // Address - u16_to_b2_big_endian((buf+7), 2); // Size - buf[9] = data; - buf[10] = 0xFF; + cmd[0] = XPRG_CMD_WRITE_MEM; + cmd[1] = tpi_get_memtype(mem); + cmd[2] = 0; // Page Mode - Not used + u32_to_b4_big_endian((cmd+3), paddr); // Address + u16_to_b2_big_endian((cmd+7), 2); // Size + cmd[9] = data; + cmd[10] = 0xFF; // len = 11 if no n_word_writes + cmd[11] = 0xFF; + cmd[12] = 0xFF; // len = 13 if n_word_writes == 2 + cmd[13] = 0xFF; + cmd[14] = 0xFF; + cmd[15] = 0xFF; + cmd[16] = 0xFF; // len = 17 if n_word_writes == 4 - if (jtag3_send_tpi(pgm, buf, len) < 0) - return -1; - - result = jtag3_recv_tpi(pgm, &resp); - if (result < 0) { - pmsg_error("error in communication, received status 0x%02x\n", result); - return -1; + if (mem->n_word_writes != 0) { + if (mem->n_word_writes == 2) + len = 13; + else if (mem->n_word_writes == 4) + len = 17; } + + if ((status = jtag3_command_tpi(pgm, cmd, len, &resp, "write byte")) < 0) + return -1; free(resp); return 0; } static int jtag3_chip_erase_tpi(const PROGRAMMER *pgm, const AVRPART *p) { const size_t len = 6; - unsigned char buf[6]; // Using "len" as array length causes msvc build jobs to fail with error C2057: expected constant expression + unsigned char cmd[6]; // Using "len" as array length causes msvc build jobs to fail with error C2057: expected constant expression unsigned char* resp; - int result; + int status; unsigned long paddr = 0UL; AVRMEM *m = avr_locate_mem(p, "flash"); @@ -2760,21 +2742,15 @@ static int jtag3_chip_erase_tpi(const PROGRAMMER *pgm, const AVRPART *p) { return LIBAVRDUDE_GENERAL_FAILURE; } + // An erase is triggered by an access to the hi-byte paddr = m->offset | 0x01; - buf[0] = XPRG_CMD_ERASE; - buf[1] = XPRG_ERASE_CHIP; - // An erase is triggered by an access to the hi-byte - u32_to_b4_big_endian((buf+2), paddr); + cmd[0] = XPRG_CMD_ERASE; + cmd[1] = XPRG_ERASE_CHIP; + u32_to_b4_big_endian((cmd+2), paddr); - if (jtag3_send_tpi(pgm, buf, len) < 0) + if ((status = jtag3_command_tpi(pgm, cmd, len, &resp, "chip erase")) < 0) return -1; - - result = jtag3_recv_tpi(pgm, &resp); - if (result < 0) { - pmsg_error("error in communication, received status 0x%02x\n", result); - return -1; - } free(resp); return 0; } From e87a9b59b63bef109aea2784f7d4ae5b8ecc0231 Mon Sep 17 00:00:00 2001 From: Jan Egil Ruud Date: Wed, 30 Nov 2022 23:08:55 +0100 Subject: [PATCH 11/22] #822 Added and tested TPI support for AtmelICE, PowerDebugger, PICkit4 and Snap. --- src/avrdude.conf.in | 68 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/src/avrdude.conf.in b/src/avrdude.conf.in index d96a31b8..e27aba0f 100644 --- a/src/avrdude.conf.in +++ b/src/avrdude.conf.in @@ -2177,6 +2177,19 @@ programmer usbpid = 0x2141; ; +#------------------------------------------------------------ +# atmelice_tpi +#------------------------------------------------------------ + +programmer + id = "atmelice_tpi"; + desc = "Atmel-ICE (ARM/AVR) in TPI mode"; + type = "jtagice3_tpi"; + prog_modes = PM_TPI; + connection_type = usb; + usbpid = 0x2141; +; + #------------------------------------------------------------ # powerdebugger #------------------------------------------------------------ @@ -2243,6 +2256,19 @@ programmer usbpid = 0x2144; ; +#------------------------------------------------------------ +# powerdebugger_tpi +#------------------------------------------------------------ + +programmer + id = "powerdebugger_tpi"; + desc = "Atmel PowerDebugger (ARM/AVR) in TPI mode"; + type = "jtagice3_tpi"; + prog_modes = PM_TPI; + connection_type = usb; + usbpid = 0x2144; +; + #------------------------------------------------------------ # pickit4_updi #------------------------------------------------------------ @@ -2283,6 +2309,19 @@ programmer usbpid = 0x2177, 0x2178, 0x2179; ; +#------------------------------------------------------------ +# pickit4_tpi +#------------------------------------------------------------ + +programmer + id = "pickit4_tpi"; + desc = "MPLAB(R) PICkit 4 in TPI mode"; + type = "jtagice3_tpi"; + prog_modes = PM_TPI; + connection_type = usb; + usbpid = 0x2177, 0x2178, 0x2179; +; + #------------------------------------------------------------ # snap_updi #------------------------------------------------------------ @@ -2323,6 +2362,19 @@ programmer usbpid = 0x2180, 0x217f, 0x2181; ; +#------------------------------------------------------------ +# snap_tpi +#------------------------------------------------------------ + +programmer + id = "snap_tpi"; + desc = "MPLAB(R) SNAP in TPI mode"; + type = "jtagice3_tpi"; + prog_modes = PM_TPI; + connection_type = usb; + usbpid = 0x2180, 0x217f, 0x2181; +; + #------------------------------------------------------------ # pkobn_updi #------------------------------------------------------------ @@ -13358,6 +13410,14 @@ part parent ".reduced_core_tiny" offset = 0x4000; blocksize = 128; ; + + memory "fuse" + size = 1; + page_size = 16; + n_word_writes = 2; + offset = 0x3f40; + blocksize = 4; + ; ; #------------------------------------------------------------ @@ -13378,6 +13438,14 @@ part parent ".reduced_core_tiny" offset = 0x4000; blocksize = 128; ; + + memory "fuse" + size = 1; + page_size = 16; + n_word_writes = 4; + offset = 0x3f40; + blocksize = 4; + ; ; #------------------------------------------------------------ From 95160e88015e7448ff722e04a8c759a1333c1509 Mon Sep 17 00:00:00 2001 From: Jan Egil Ruud Date: Wed, 30 Nov 2022 23:21:30 +0100 Subject: [PATCH 12/22] Changed verbose level on TPI initialize notice. --- src/jtag3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jtag3.c b/src/jtag3.c index d53ba15e..94861f23 100644 --- a/src/jtag3.c +++ b/src/jtag3.c @@ -2593,7 +2593,7 @@ static int jtag3_initialize_tpi(const PROGRAMMER *pgm, const AVRPART *p) { unsigned char* resp; int status; - pmsg_info("jtag3_initialize_tpi() start\n"); + pmsg_notice2("jtag3_initialize_tpi() start\n"); cmd[0] = XPRG_CMD_ENTER_PROGMODE; From b52bd393de85d07dd6764cdab013446edaee04d8 Mon Sep 17 00:00:00 2001 From: Jan Egil Ruud Date: Wed, 30 Nov 2022 23:39:37 +0100 Subject: [PATCH 13/22] #822 Added TPI support for JTAGICE3. --- src/avrdude.conf.in | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/avrdude.conf.in b/src/avrdude.conf.in index e27aba0f..b8365316 100644 --- a/src/avrdude.conf.in +++ b/src/avrdude.conf.in @@ -2031,6 +2031,19 @@ programmer usbpid = 0x2110, 0x2140; ; +#------------------------------------------------------------ +# jtag3tpi +#------------------------------------------------------------ + +programmer + id = "jtag3tpi"; + desc = "Atmel AVR JTAGICE3 in TPI mode"; + type = "jtagice3_tpi"; + prog_modes = PM_TPI; + connection_type = usb; + usbpid = 0x2110, 0x2140; +; + #------------------------------------------------------------ # xplainedpro #------------------------------------------------------------ From b643f0a1a03a69c3043a416ceba5bbfc5ba33ba9 Mon Sep 17 00:00:00 2001 From: Jan Egil Ruud Date: Wed, 30 Nov 2022 23:49:20 +0100 Subject: [PATCH 14/22] #822 Fixed bug in TPI byte write for ATtiny20 and ATtiny40. --- src/jtag3.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/jtag3.c b/src/jtag3.c index 94861f23..f099b245 100644 --- a/src/jtag3.c +++ b/src/jtag3.c @@ -2689,6 +2689,7 @@ static int jtag3_erase_tpi(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM static int jtag3_write_byte_tpi(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, unsigned long addr, unsigned char data) { size_t len = 11; + size_t data_size = 2; unsigned char cmd[17]; unsigned char* resp; int status; @@ -2702,11 +2703,22 @@ static int jtag3_write_byte_tpi(const PROGRAMMER *pgm, const AVRPART *p, const A paddr = mem->offset + addr; + if (mem->n_word_writes != 0) { + if (mem->n_word_writes == 2) { + len = 13; + data_size = 4; + } + else if (mem->n_word_writes == 4) { + len = 17; + data_size = 8; + } + } + cmd[0] = XPRG_CMD_WRITE_MEM; cmd[1] = tpi_get_memtype(mem); cmd[2] = 0; // Page Mode - Not used - u32_to_b4_big_endian((cmd+3), paddr); // Address - u16_to_b2_big_endian((cmd+7), 2); // Size + u32_to_b4_big_endian((cmd+3), paddr); // Address + u16_to_b2_big_endian((cmd+7), data_size); // Size cmd[9] = data; cmd[10] = 0xFF; // len = 11 if no n_word_writes cmd[11] = 0xFF; @@ -2716,13 +2728,6 @@ static int jtag3_write_byte_tpi(const PROGRAMMER *pgm, const AVRPART *p, const A cmd[15] = 0xFF; cmd[16] = 0xFF; // len = 17 if n_word_writes == 4 - if (mem->n_word_writes != 0) { - if (mem->n_word_writes == 2) - len = 13; - else if (mem->n_word_writes == 4) - len = 17; - } - if ((status = jtag3_command_tpi(pgm, cmd, len, &resp, "write byte")) < 0) return -1; free(resp); From e18b5c4fb098174d0c3b3ff5a37b1e7ff38c6b6f Mon Sep 17 00:00:00 2001 From: Jan Egil Ruud Date: Thu, 1 Dec 2022 00:01:29 +0100 Subject: [PATCH 15/22] Made the code a little prettier. --- src/jtag3.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/jtag3.c b/src/jtag3.c index f099b245..7b004e74 100644 --- a/src/jtag3.c +++ b/src/jtag3.c @@ -2653,7 +2653,7 @@ static int jtag3_read_byte_tpi(const PROGRAMMER *pgm, const AVRPART *p, const AV u32_to_b4_big_endian((cmd+2), paddr); // Address u16_to_b2_big_endian((cmd+6), 1); // Size - if ((status = jtag3_command_tpi(pgm, cmd, len, &resp, "read byte")) < 0) + if ((status = jtag3_command_tpi(pgm, cmd, len, &resp, "Read Byte")) < 0) return -1; *value = resp[2]; free(resp); @@ -2680,7 +2680,7 @@ static int jtag3_erase_tpi(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM paddr = (mem->offset + addr) | 0x01; // An erase is triggered by an access to the hi-byte u32_to_b4_big_endian((cmd+2), paddr); - if ((status = jtag3_command_tpi(pgm, cmd, len, &resp, "erase")) < 0) + if ((status = jtag3_command_tpi(pgm, cmd, len, &resp, "Erase")) < 0) return -1; free(resp); return 0; @@ -2728,7 +2728,7 @@ static int jtag3_write_byte_tpi(const PROGRAMMER *pgm, const AVRPART *p, const A cmd[15] = 0xFF; cmd[16] = 0xFF; // len = 17 if n_word_writes == 4 - if ((status = jtag3_command_tpi(pgm, cmd, len, &resp, "write byte")) < 0) + if ((status = jtag3_command_tpi(pgm, cmd, len, &resp, "Write Byte")) < 0) return -1; free(resp); return 0; @@ -2754,7 +2754,7 @@ static int jtag3_chip_erase_tpi(const PROGRAMMER *pgm, const AVRPART *p) { cmd[1] = XPRG_ERASE_CHIP; u32_to_b4_big_endian((cmd+2), paddr); - if ((status = jtag3_command_tpi(pgm, cmd, len, &resp, "chip erase")) < 0) + if ((status = jtag3_command_tpi(pgm, cmd, len, &resp, "Chip Erase")) < 0) return -1; free(resp); return 0; @@ -2787,7 +2787,7 @@ static int jtag3_paged_load_tpi(const PROGRAMMER *pgm, const AVRPART *p, m->desc, page_size, addr, n_bytes); if(m->offset) - msg_notice2(" mapped to address: 0x%04x\n", (addr+m->offset)); + imsg_notice2("mapped to address: 0x%04x\n", (addr+m->offset)); cmd[0] = XPRG_CMD_READ_MEM; cmd[1] = tpi_get_memtype(m); @@ -2807,7 +2807,7 @@ static int jtag3_paged_load_tpi(const PROGRAMMER *pgm, const AVRPART *p, u32_to_b4_big_endian((cmd+2), addr + m->offset); // Address u16_to_b2_big_endian((cmd+6), block_size); // Size - 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; if (resp[1] != XPRG_ERR_OK || @@ -2839,7 +2839,7 @@ static int jtag3_paged_write_tpi(const PROGRAMMER *pgm, const AVRPART *p, pmsg_notice2("jtag3_paged_write_tpi(.., %s, %d, 0x%04x, %d)\n", m->desc, page_size, addr, n_bytes); if(m->offset) - msg_notice2(" mapped to address: 0x%04x\n", (addr+m->offset)); + imsg_notice2("mapped to address: 0x%04x\n", (addr+m->offset)); if (page_size == 0) page_size = m->page_size; @@ -2874,7 +2874,7 @@ static int jtag3_paged_write_tpi(const PROGRAMMER *pgm, const AVRPART *p, memcpy(cmd + 9, m->buf + addr, block_size); if ((status = jtag3_command_tpi(pgm, cmd, page_size + 9, - &resp, "write memory")) < 0) { + &resp, "Write Memory")) < 0) { free(cmd); serial_recv_timeout = otimeout; return -1; From bb808e8d5fb438dcc736e511a0d54118cf7c2dfb Mon Sep 17 00:00:00 2001 From: Jan Egil Ruud Date: Thu, 1 Dec 2022 15:16:23 +0100 Subject: [PATCH 16/22] Skip chaching when size of memory is 0. --- src/avrcache.c | 18 +++++++++++------- src/jtag3.c | 6 +----- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/avrcache.c b/src/avrcache.c index a0fa9082..ebb8fd89 100644 --- a/src/avrcache.c +++ b/src/avrcache.c @@ -343,7 +343,7 @@ int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p) { for(size_t i = 0; i < sizeof mems/sizeof*mems; i++) { AVRMEM *mem = mems[i].mem; AVR_Cache *cp = mems[i].cp; - if(!mem || !cp->cont) + if(!mem || !cp->cont || !cp->size) continue; for(int pgno = 0, n = 0; n < cp->size; pgno++, n += cp->page_size) { @@ -367,6 +367,8 @@ int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p) { AVRMEM *mem = mems[i].mem; AVR_Cache *cp = mems[i].cp; + if(!cp->size) + continue; if(!cp->cont) // Ensure cache is initialised from now on if(initCache(cp, pgm, p) < 0) { if(quell_progress) @@ -419,7 +421,7 @@ int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p) { for(size_t i = 0; i < sizeof mems/sizeof*mems; i++) { AVRMEM *mem = mems[i].mem; AVR_Cache *cp = mems[i].cp; - if(!mem) + if(!mem || !cp->size) continue; for(int pgno = 0, n = 0; n < cp->size; pgno++, n += cp->page_size) @@ -433,7 +435,7 @@ int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p) { for(size_t i = 0; i < sizeof mems/sizeof*mems; i++) { AVRMEM *mem = mems[i].mem; AVR_Cache *cp = mems[i].cp; - if(!mem) + if(!mem || !cp->size) continue; for(int ird = 0, pgno = 0, n = 0; n < cp->size; pgno++, n += cp->page_size) { @@ -460,7 +462,7 @@ int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p) { for(size_t i = 0; i < sizeof mems/sizeof*mems; i++) { AVRMEM *mem = mems[i].mem; AVR_Cache *cp = mems[i].cp; - if(!mem) + if(!mem || !cp->size) continue; if(mems[i].isflash) { // flash @@ -508,7 +510,7 @@ int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p) { for(size_t i = 0; i < sizeof mems/sizeof*mems; i++) { AVRMEM *mem = mems[i].mem; AVR_Cache *cp = mems[i].cp; - if(!mem) + if(!mem || !cp->size) continue; for(int pgno = 0, n = 0; n < cp->size; pgno++, n += cp->page_size) @@ -522,7 +524,7 @@ int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p) { for(size_t i = 0; i < sizeof mems/sizeof*mems; i++) { AVRMEM *mem = mems[i].mem; AVR_Cache *cp = mems[i].cp; - if(!mem || !cp->cont) + if(!mem || !cp->cont || !cp->size) continue; for(int iwr = 0, pgno = 0, n = 0; n < cp->size; pgno++, n += cp->page_size) { @@ -644,7 +646,7 @@ int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p) { AVRMEM *mem = mems[i].mem; AVR_Cache *cp = mems[i].cp; - if(!mem || !avr_has_paged_access(pgm, mem)) + if(!mem || !cp->size || !avr_has_paged_access(pgm, mem)) continue; if(!cp->cont) // Init cache if needed @@ -734,6 +736,8 @@ int avr_reset_cache(const PROGRAMMER *pgm, const AVRPART *p) { for(size_t i = 0; i < sizeof mems/sizeof*mems; i++) { AVR_Cache *cp = mems[i]; + if(!cp->size) + continue; if(cp->cont) free(cp->cont); if(cp->copy) diff --git a/src/jtag3.c b/src/jtag3.c index 7b004e74..481e9783 100644 --- a/src/jtag3.c +++ b/src/jtag3.c @@ -2509,10 +2509,6 @@ unsigned char tpi_get_memtype(const AVRMEM *mem) { return memtype; } -// void tpi_print_error_status(unsigned char error) { -// pmsg_error("error communicating with programmer, received status 0x%02x\n", error); -// } - /* * Send the data as a JTAGICE3 encapsulated TPI packet. */ @@ -2589,7 +2585,7 @@ int jtag3_command_tpi(const PROGRAMMER *pgm, unsigned char *cmd, unsigned int cm * initialize the AVR device and prepare it to accept commands */ static int jtag3_initialize_tpi(const PROGRAMMER *pgm, const AVRPART *p) { - unsigned char cmd[4]; + unsigned char cmd[3]; unsigned char* resp; int status; From f78e14ee96da1c493f09d007d32141a5bf02f85d Mon Sep 17 00:00:00 2001 From: Jan Egil Ruud Date: Thu, 1 Dec 2022 20:01:11 +0100 Subject: [PATCH 17/22] Revert "Skip chaching when size of memory is 0." This reverts commit bb808e8d5fb438dcc736e511a0d54118cf7c2dfb. --- src/avrcache.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/avrcache.c b/src/avrcache.c index ebb8fd89..a0fa9082 100644 --- a/src/avrcache.c +++ b/src/avrcache.c @@ -343,7 +343,7 @@ int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p) { for(size_t i = 0; i < sizeof mems/sizeof*mems; i++) { AVRMEM *mem = mems[i].mem; AVR_Cache *cp = mems[i].cp; - if(!mem || !cp->cont || !cp->size) + if(!mem || !cp->cont) continue; for(int pgno = 0, n = 0; n < cp->size; pgno++, n += cp->page_size) { @@ -367,8 +367,6 @@ int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p) { AVRMEM *mem = mems[i].mem; AVR_Cache *cp = mems[i].cp; - if(!cp->size) - continue; if(!cp->cont) // Ensure cache is initialised from now on if(initCache(cp, pgm, p) < 0) { if(quell_progress) @@ -421,7 +419,7 @@ int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p) { for(size_t i = 0; i < sizeof mems/sizeof*mems; i++) { AVRMEM *mem = mems[i].mem; AVR_Cache *cp = mems[i].cp; - if(!mem || !cp->size) + if(!mem) continue; for(int pgno = 0, n = 0; n < cp->size; pgno++, n += cp->page_size) @@ -435,7 +433,7 @@ int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p) { for(size_t i = 0; i < sizeof mems/sizeof*mems; i++) { AVRMEM *mem = mems[i].mem; AVR_Cache *cp = mems[i].cp; - if(!mem || !cp->size) + if(!mem) continue; for(int ird = 0, pgno = 0, n = 0; n < cp->size; pgno++, n += cp->page_size) { @@ -462,7 +460,7 @@ int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p) { for(size_t i = 0; i < sizeof mems/sizeof*mems; i++) { AVRMEM *mem = mems[i].mem; AVR_Cache *cp = mems[i].cp; - if(!mem || !cp->size) + if(!mem) continue; if(mems[i].isflash) { // flash @@ -510,7 +508,7 @@ int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p) { for(size_t i = 0; i < sizeof mems/sizeof*mems; i++) { AVRMEM *mem = mems[i].mem; AVR_Cache *cp = mems[i].cp; - if(!mem || !cp->size) + if(!mem) continue; for(int pgno = 0, n = 0; n < cp->size; pgno++, n += cp->page_size) @@ -524,7 +522,7 @@ int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p) { for(size_t i = 0; i < sizeof mems/sizeof*mems; i++) { AVRMEM *mem = mems[i].mem; AVR_Cache *cp = mems[i].cp; - if(!mem || !cp->cont || !cp->size) + if(!mem || !cp->cont) continue; for(int iwr = 0, pgno = 0, n = 0; n < cp->size; pgno++, n += cp->page_size) { @@ -646,7 +644,7 @@ int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p) { AVRMEM *mem = mems[i].mem; AVR_Cache *cp = mems[i].cp; - if(!mem || !cp->size || !avr_has_paged_access(pgm, mem)) + if(!mem || !avr_has_paged_access(pgm, mem)) continue; if(!cp->cont) // Init cache if needed @@ -736,8 +734,6 @@ int avr_reset_cache(const PROGRAMMER *pgm, const AVRPART *p) { for(size_t i = 0; i < sizeof mems/sizeof*mems; i++) { AVR_Cache *cp = mems[i]; - if(!cp->size) - continue; if(cp->cont) free(cp->cont); if(cp->copy) From dc64fb716f581ce7062e025783b9dfd21dd89c92 Mon Sep 17 00:00:00 2001 From: Jan Egil Ruud Date: Thu, 1 Dec 2022 20:05:55 +0100 Subject: [PATCH 18/22] Fix wrongfully call to initCache() according to stefanrueger's instructions. --- src/avrcache.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/avrcache.c b/src/avrcache.c index a0fa9082..3215d720 100644 --- a/src/avrcache.c +++ b/src/avrcache.c @@ -367,6 +367,9 @@ int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p) { AVRMEM *mem = mems[i].mem; AVR_Cache *cp = mems[i].cp; + if(!mem) + continue; + if(!cp->cont) // Ensure cache is initialised from now on if(initCache(cp, pgm, p) < 0) { if(quell_progress) From 8db18e64edb0ec35c2d88f4349973b7fa43a7b78 Mon Sep 17 00:00:00 2001 From: Jan Egil Ruud Date: Thu, 1 Dec 2022 20:12:26 +0100 Subject: [PATCH 19/22] Remove redundant mem-check. --- src/avrcache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/avrcache.c b/src/avrcache.c index 3215d720..7a57edb8 100644 --- a/src/avrcache.c +++ b/src/avrcache.c @@ -378,7 +378,7 @@ int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p) { return LIBAVRDUDE_GENERAL_FAILURE; } - if(chiperase || !mem || mems[i].zopaddr < 0) + if(chiperase || mems[i].zopaddr < 0) continue; int n=mems[i].zopaddr; From 2561d87fbd7b13570472d239d91c652101451d85 Mon Sep 17 00:00:00 2001 From: Jan Egil Ruud Date: Mon, 12 Dec 2022 14:10:42 +0100 Subject: [PATCH 20/22] #822 Removed JTAGICE3 TPI support. --- src/avrdude.conf.in | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/avrdude.conf.in b/src/avrdude.conf.in index b8365316..e27aba0f 100644 --- a/src/avrdude.conf.in +++ b/src/avrdude.conf.in @@ -2031,19 +2031,6 @@ programmer usbpid = 0x2110, 0x2140; ; -#------------------------------------------------------------ -# jtag3tpi -#------------------------------------------------------------ - -programmer - id = "jtag3tpi"; - desc = "Atmel AVR JTAGICE3 in TPI mode"; - type = "jtagice3_tpi"; - prog_modes = PM_TPI; - connection_type = usb; - usbpid = 0x2110, 0x2140; -; - #------------------------------------------------------------ # xplainedpro #------------------------------------------------------------ From af43a7757de431260ae37dc40fbfae410b49720e Mon Sep 17 00:00:00 2001 From: Jan Egil Ruud Date: Mon, 12 Dec 2022 14:20:16 +0100 Subject: [PATCH 21/22] #822 Print Vtarget when using TPI. --- src/jtag3.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/jtag3.c b/src/jtag3.c index 481e9783..27ce51a8 100644 --- a/src/jtag3.c +++ b/src/jtag3.c @@ -2612,6 +2612,12 @@ static int jtag3_initialize_tpi(const PROGRAMMER *pgm, const AVRPART *p) { if ((status = jtag3_command_tpi(pgm, cmd, 3, &resp, "Set NVMCSR")) < 0) return -1; free(resp); + + if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_VTARGET, cmd, 2) < 0) + return -1; + fmsg_out(stderr, "%sVtarget %s: %.2f V\n", "", + verbose? "": " ", b2_to_u16(cmd)/1000.0); + return 0; } From f08f771ab49c7b5a3374a3cf3ebb1672f0f80e05 Mon Sep 17 00:00:00 2001 From: Jan Egil Ruud Date: Tue, 13 Dec 2022 15:07:14 +0100 Subject: [PATCH 22/22] #822 Fixed print_parms for TPI. --- src/jtag3.c | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/jtag3.c b/src/jtag3.c index 27ce51a8..7e660b92 100644 --- a/src/jtag3.c +++ b/src/jtag3.c @@ -2419,32 +2419,35 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp) { } } - if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_MEGA_PROG, buf, 2) < 0) - return; + // Print clocks if programmer typ is not TPI + if (strcmp(pgm->type, "JTAGICE3_TPI")) { + if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_MEGA_PROG, buf, 2) < 0) + return; - if (b2_to_u16(buf) > 0) { - fmsg_out(fp, "%sJTAG clock megaAVR/program : %u kHz\n", p, b2_to_u16(buf)); - } + if (b2_to_u16(buf) > 0) { + 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) - return; + if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_MEGA_DEBUG, buf, 2) < 0) + return; - if (b2_to_u16(buf) > 0) { - fmsg_out(fp, "%sJTAG clock megaAVR/debug : %u kHz\n", p, b2_to_u16(buf)); - } + if (b2_to_u16(buf) > 0) { + 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 (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)); - } + if (b2_to_u16(buf) > 0) { + fmsg_out(fp, "%sJTAG clock Xmega : %u kHz\n", p, b2_to_u16(buf)); + } - if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_XMEGA_PDI, buf, 2) < 0) - return; + if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_XMEGA_PDI, buf, 2) < 0) + return; - if (b2_to_u16(buf) > 0) { - fmsg_out(fp, "%sPDI/UPDI clock Xmega/megaAVR : %u kHz\n", p, b2_to_u16(buf)); + if (b2_to_u16(buf) > 0) { + fmsg_out(fp, "%sPDI/UPDI clock Xmega/megaAVR : %u kHz\n", p, b2_to_u16(buf)); + } } } @@ -2613,10 +2616,7 @@ static int jtag3_initialize_tpi(const PROGRAMMER *pgm, const AVRPART *p) { return -1; free(resp); - if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_VTARGET, cmd, 2) < 0) - return -1; - fmsg_out(stderr, "%sVtarget %s: %.2f V\n", "", - verbose? "": " ", b2_to_u16(cmd)/1000.0); + jtag3_print_parms(pgm, stderr); return 0; }