diff --git a/src/avrcache.c b/src/avrcache.c index 98370827..c7bfae3a 100644 --- a/src/avrcache.c +++ b/src/avrcache.c @@ -372,6 +372,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) @@ -380,7 +383,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; diff --git a/src/avrdude.conf.in b/src/avrdude.conf.in index cdc7fff1..11da317f 100644 --- a/src/avrdude.conf.in +++ b/src/avrdude.conf.in @@ -2131,6 +2131,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 #------------------------------------------------------------ @@ -2197,6 +2210,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 #------------------------------------------------------------ @@ -2263,6 +2289,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 #------------------------------------------------------------ @@ -2303,6 +2342,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 #------------------------------------------------------------ @@ -2343,6 +2395,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 #------------------------------------------------------------ @@ -13440,12 +13505,6 @@ part offset = 0x3f00; ; - memory "lockbits" - size = 1; - page_size = 16; - offset = 0x3f00; - ; - memory "signature" size = 3; page_size = 16; @@ -13539,6 +13598,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; + ; ; #------------------------------------------------------------ @@ -13559,6 +13626,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; + ; ; #------------------------------------------------------------ @@ -13578,6 +13653,12 @@ part parent ".reduced_core_tiny" offset = 0x4000; blocksize = 128; ; + + memory "sigrow" + size = 16; + page_size = 16; + offset = 0x3fc6; + ; ; #------------------------------------------------------------ @@ -13597,6 +13678,12 @@ part parent ".reduced_core_tiny" offset = 0x4000; blocksize = 128; ; + + memory "sigrow" + size = 16; + page_size = 16; + offset = 0x3fc6; + ; ; #------------------------------------------------------------ diff --git a/src/jtag3.c b/src/jtag3.c index 146bed4b..7e660b92 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,11 +84,12 @@ 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) #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); @@ -164,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; @@ -196,9 +213,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"); @@ -236,47 +253,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; @@ -288,29 +303,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]); } } @@ -331,9 +344,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"); @@ -360,58 +373,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; @@ -421,11 +432,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 */ @@ -448,11 +458,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); @@ -460,60 +469,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; } @@ -771,7 +775,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; @@ -783,7 +787,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 @@ -802,8 +806,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; @@ -824,8 +827,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); @@ -850,9 +853,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. */ @@ -918,9 +921,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; } @@ -970,15 +971,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); } @@ -1067,8 +1068,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); @@ -1078,8 +1078,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], @@ -1089,8 +1088,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; @@ -1101,41 +1099,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; @@ -1144,11 +1141,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; @@ -1166,8 +1161,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; @@ -1175,24 +1169,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); } } @@ -1205,7 +1195,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; } @@ -1250,8 +1240,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; @@ -1262,18 +1251,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); } } @@ -1283,11 +1272,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 { @@ -1315,7 +1304,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; @@ -1324,9 +1313,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; } /* @@ -1345,12 +1334,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); @@ -1412,15 +1401,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; @@ -1484,7 +1472,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)) { @@ -1498,7 +1486,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 @@ -1528,7 +1516,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) @@ -1541,8 +1529,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; @@ -1613,8 +1600,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"); @@ -1636,7 +1622,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); @@ -1644,8 +1630,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); @@ -1692,8 +1677,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; @@ -1711,7 +1695,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"); @@ -1734,11 +1719,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; @@ -1782,7 +1767,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; @@ -1798,9 +1783,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]; @@ -1809,7 +1793,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) @@ -1855,7 +1839,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); @@ -1867,7 +1851,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); @@ -1882,8 +1866,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; @@ -1982,7 +1965,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]; @@ -2053,8 +2036,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; @@ -2138,7 +2120,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); @@ -2195,9 +2177,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]; @@ -2212,7 +2193,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; @@ -2235,9 +2216,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]; @@ -2245,10 +2225,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; } @@ -2283,7 +2262,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 @@ -2348,9 +2327,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); } @@ -2362,7 +2340,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)) { @@ -2374,7 +2352,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) @@ -2386,7 +2364,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 @@ -2399,7 +2377,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 @@ -2410,7 +2388,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) @@ -2422,7 +2400,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 @@ -2435,38 +2413,41 @@ 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; } } - 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)); + } } } @@ -2513,6 +2494,403 @@ 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 if (strcmp(mem->desc, "sigrow") == 0) { + memtype = XPRG_MEM_TYPE_LOCKBITS; + } else { + memtype = XPRG_MEM_TYPE_APPL; + } + return memtype; +} + +/* + * 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("jtag3_send_tpi(): out of memory for command packet\n"); + exit(1); + } + + cmdbuf[0] = SCOPE_AVR_TPI; + memcpy(cmdbuf + 1, data, len); + + msg_trace("[TPI send] "); + for (size_t i=1; i<=len; i++) + msg_trace("0x%02x ", cmdbuf[i]); + msg_trace("\n"); + + rv = jtag3_send(pgm, cmdbuf, len + 1); + free(cmdbuf); + + return rv; +} + +int jtag3_recv_tpi(const PROGRAMMER *pgm, unsigned char **msg) { + int rv; + + rv = jtag3_recv(pgm, msg); + + if (rv <= 0) { + pmsg_error("jtag3_recv_tpi(): unable to receive\n"); + return -1; + } + rv = rv - 1; + memcpy(*msg, *msg + 1, rv); + + msg_trace("[TPI recv] "); + for (size_t i=0; idesc, addr); + + paddr = mem->offset + addr; + + 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 ((status = jtag3_command_tpi(pgm, cmd, len, &resp, "Read Byte")) < 0) + return -1; + *value = resp[2]; + free(resp); + return 0; +} + +static int jtag3_erase_tpi(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, + unsigned long addr) { + const size_t len = 6; + 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 status; + unsigned long paddr = 0UL; + + cmd[0] = XPRG_CMD_ERASE; + if (strcmp(mem->desc, "fuse") == 0) { + cmd[1] = XPRG_ERASE_CONFIG; + } else if (strcmp(mem->desc, "flash") == 0) { + 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((cmd+2), paddr); + + if ((status = jtag3_command_tpi(pgm, cmd, len, &resp, "Erase")) < 0) + 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) { + size_t len = 11; + size_t data_size = 2; + unsigned char cmd[17]; + unsigned char* resp; + int status; + unsigned long paddr = 0UL; + + 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; + + 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), data_size); // 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 ((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 cmd[6]; // Using "len" as array length causes msvc build jobs to fail with error C2057: expected constant expression + unsigned char* resp; + int status; + 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; + } + + // An erase is triggered by an access to the hi-byte + paddr = m->offset | 0x01; + + cmd[0] = XPRG_CMD_ERASE; + 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) + return -1; + free(resp); + return 0; +} + +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"); +} + +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; + + msg_notice2("\n"); + pmsg_notice2("jtag3_paged_load_tpi(.., %s, %d, 0x%04x, %d)\n", + m->desc, page_size, addr, n_bytes); + + if(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); + + 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; +} + +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) + imsg_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"; @@ -2677,3 +3055,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_tpi; + + /* + * optional functions + */ + pgm->paged_write = jtag3_paged_write_tpi; + pgm->paged_load = jtag3_paged_load_tpi; + 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..157d4982 100644 --- a/src/jtag3.h +++ b/src/jtag3.h @@ -31,23 +31,25 @@ 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[]; 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..2e971729 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,60 @@ #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 + +#define TPI_NVMCMD_ADDRESS 0x33 +#define TPI_NVMCSR_ADDRESS 0x32 + + #if !defined(JTAG3_PRIVATE_EXPORTED) struct mega_device_desc { diff --git a/src/pgm_type.c b/src/pgm_type.c index f14b065b..91400fea 100644 --- a/src/pgm_type.c +++ b/src/pgm_type.c @@ -87,6 +87,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 bb086c10..20b8a1ac 100644 --- a/src/stk500v2.c +++ b/src/stk500v2.c @@ -3605,18 +3605,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 560f143e..7d55ad19 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