From 10ccf0f515f17575f8607d02a9ed148e3b074176 Mon Sep 17 00:00:00 2001 From: Jan Egil Ruud Date: Mon, 21 Nov 2022 21:18:13 +0100 Subject: [PATCH] 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