avrdude/src/jtag3.c

3159 lines
89 KiB
C
Raw Normal View History

/*
* avrdude - A Downloader/Uploader for AVR device programmers
* Copyright (C) 2012 Joerg Wunsch <j@uriah.heep.sax.de>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* $Id$ */
/*
* avrdude interface for Atmel JTAGICE3 programmer
*/
#include "ac_cfg.h"
#include <ctype.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <errno.h>
#include <unistd.h>
#include <sys/time.h>
#include <time.h>
#include "avrdude.h"
#include "libavrdude.h"
#include "crc16.h"
#include "jtag3.h"
#include "jtag3_private.h"
#include "usbdevs.h"
/*
* Private data for this programmer.
*/
struct pdata
{
unsigned short command_sequence; /* Next cmd seqno to issue. */
/*
* See jtag3_read_byte() for an explanation of the flash and
* EEPROM page caches.
*/
unsigned char *flash_pagecache;
unsigned long flash_pageaddr;
unsigned int flash_pagesize;
unsigned char *eeprom_pagecache;
unsigned long eeprom_pageaddr;
unsigned int eeprom_pagesize;
int prog_enabled; /* Cached value of PROGRAMMING status. */
/* JTAG chain stuff */
unsigned char jtagchain[4];
/* Start address of Xmega boot area */
unsigned long boot_start;
/* Flag for triggering HV UPDI */
bool use_hvupdi;
/* Function to set the appropriate clock parameter */
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
int (*set_sck)(const PROGRAMMER *, unsigned char *);
};
#define PDATA(pgm) ((struct pdata *)(pgm->cookie))
/*
* 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_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)
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
static int jtag3_open(PROGRAMMER *pgm, const char *port);
static int jtag3_edbg_prepare(const PROGRAMMER *pgm);
static int jtag3_edbg_signoff(const PROGRAMMER *pgm);
static int jtag3_edbg_send(const PROGRAMMER *pgm, unsigned char *data, size_t len);
static int jtag3_edbg_recv_frame(const PROGRAMMER *pgm, unsigned char **msg);
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
static int jtag3_initialize(const PROGRAMMER *pgm, const AVRPART *p);
static int jtag3_chip_erase(const PROGRAMMER *pgm, const AVRPART *p);
static int jtag3_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
unsigned long addr, unsigned char * value);
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
static int jtag3_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
unsigned long addr, unsigned char data);
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
static int jtag3_set_sck_period(const PROGRAMMER *pgm, double v);
void jtag3_display(const PROGRAMMER *pgm, const char *p);
void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp);
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
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);
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
static unsigned char jtag3_memtype(const PROGRAMMER *pgm, const AVRPART *p, unsigned long addr);
static unsigned int jtag3_memaddr(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m, unsigned long addr);
void jtag3_setup(PROGRAMMER * pgm)
{
if ((pgm->cookie = malloc(sizeof(struct pdata))) == 0) {
pmsg_error("out of memory allocating private data\n");
exit(1);
}
memset(pgm->cookie, 0, sizeof(struct pdata));
}
void jtag3_teardown(PROGRAMMER * pgm)
{
free(pgm->cookie);
}
static unsigned long
b4_to_u32(unsigned char *b)
{
unsigned long l;
l = b[0];
l += (unsigned)b[1] << 8;
l += (unsigned)b[2] << 16;
l += (unsigned)b[3] << 24;
return l;
}
static void
u32_to_b4(unsigned char *b, unsigned long l)
{
b[0] = l & 0xff;
b[1] = (l >> 8) & 0xff;
b[2] = (l >> 16) & 0xff;
b[3] = (l >> 24) & 0xff;
}
static unsigned short
b2_to_u16(unsigned char *b)
{
unsigned short l;
l = b[0];
l += (unsigned)b[1] << 8;
return l;
}
static void
u16_to_b2(unsigned char *b, unsigned short l)
{
b[0] = l & 0xff;
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;
}
static void jtag3_print_data(unsigned char *b, size_t s)
{
size_t i;
if (s < 2)
return;
for (i = 0; i < s; i++) {
msg_info("0x%02x", b[i]);
if (i % 16 == 15)
msg_info("\n");
else
msg_info(" ");
}
if (i % 16 != 0)
msg_info("\n");
}
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
static void jtag3_prmsg(const PROGRAMMER *pgm, unsigned char *data, size_t len) {
if (verbose >= 4) {
size_t i;
msg_trace("Raw message:\n");
for (i = 0; i < len; i++) {
msg_trace("%02x ", data[i]);
if (i % 16 == 15)
msg_trace("\n");
else
msg_trace(" ");
}
if (i % 16 != 0)
msg_trace("\n");
}
switch (data[0]) {
case SCOPE_INFO:
msg_info("[info] ");
break;
case SCOPE_GENERAL:
msg_info("[general] ");
break;
case SCOPE_AVR_ISP:
msg_info("[AVRISP] ");
jtag3_print_data(data + 1, len - 1);
return;
case SCOPE_AVR:
msg_info("[AVR] ");
break;
default:
msg_info("[scope 0x%02x] ", data[0]);
break;
}
switch (data[1]) {
case RSP3_OK:
msg_info("OK\n");
break;
case RSP3_FAILED:
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;
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_WRONG_MODE:
strcpy(reason, "wrong (programming) mode");
break;
case RSP3_FAIL_PDI:
strcpy(reason, "PDI failure");
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_DEBUGWIRE:
strcpy(reason, "debugWIRE communication failed");
break;
}
msg_info(", reason: %s\n", reason);
}
else {
msg_info(", unspecified reason\n");
}
break;
case RSP3_DATA:
msg_info("Data returned:\n");
jtag3_print_data(data + 2, len - 2);
break;
case RSP3_INFO:
msg_info("Info returned:\n");
for (size_t i = 2; i < len; 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");
}
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]);
}
}
static int jtag3_errcode(int reason)
{
if (reason == RSP3_FAIL_OCD_LOCKED ||
reason == RSP3_FAIL_CRC_FAILURE)
return LIBAVRDUDE_SOFTFAIL;
return LIBAVRDUDE_GENERAL_FAILURE;
}
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
static void jtag3_prevent(const PROGRAMMER *pgm, unsigned char *data, size_t len) {
if (verbose >= 4) {
size_t i;
msg_trace("Raw event:\n");
for (i = 0; i < len; i++) {
msg_trace("%02x ", data[i]);
if (i % 16 == 15)
msg_trace("\n");
else
msg_trace(" ");
}
if (i % 16 != 0)
msg_trace("\n");
}
msg_info("Event serial 0x%04x, ", (data[3] << 8) | data[2]);
switch (data[4]) {
case SCOPE_INFO:
msg_info("[info] ");
break;
case SCOPE_GENERAL:
msg_info("[general] ");
break;
case SCOPE_AVR:
msg_info("[AVR] ");
break;
default:
msg_info("[scope 0x%02x] ", data[0]);
break;
}
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]);
}
/* There are two more bytes of data which always appear to be
* 0x01, 0x00. Purpose unknown. */
}
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;
default:
msg_info("UNKNOWN 0x%02x", data[5]);
break;
}
msg_info("\n");
}
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
int jtag3_send(const PROGRAMMER *pgm, unsigned char *data, size_t len) {
unsigned char *buf;
if (pgm->flag & PGM_FL_IS_EDBG)
return jtag3_edbg_send(pgm, data, 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;
}
buf[0] = TOKEN;
buf[1] = 0; /* dummy */
u16_to_b2(buf + 2, PDATA(pgm)->command_sequence);
memcpy(buf + 4, data, len);
if (serial_send(&pgm->fd, buf, len + 4) != 0) {
pmsg_error("unable to send command to serial port\n");
free(buf);
return -1;
}
free(buf);
return 0;
}
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
static int jtag3_edbg_send(const PROGRAMMER *pgm, unsigned char *data, size_t len) {
unsigned char buf[USBDEV_MAX_XFER_3];
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);
}
msg_debug("\n");
pmsg_debug("jtag3_edbg_send(): sending %lu bytes\n", (unsigned long) len);
/* 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);
}
int frag;
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;
if (frag == 0) {
/* Only first fragment has TOKEN and seq#, thus four bytes
* less payload than subsequent fragments. */
this_len = (int) len < max_xfer - 8? (int) 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);
if(this_len < 0) {
pmsg_error("unexpected this_len = %d\n", this_len);
return -1;
}
memcpy(buf + 8, data, this_len);
}
else {
this_len = (int) len < max_xfer - 4? (int) len: max_xfer - 4;
buf[2] = (this_len) >> 8;
buf[3] = (this_len) & 0xff;
if(this_len < 0) {
pmsg_error("unexpected this_len = %d\n", this_len);
return -1;
}
memcpy(buf + 4, data, this_len);
}
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;
}
/*
* Send out all the CMSIS-DAP stuff needed to prepare the ICE.
*/
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
static int jtag3_edbg_prepare(const PROGRAMMER *pgm) {
unsigned char buf[USBDEV_MAX_XFER_3];
unsigned char status[USBDEV_MAX_XFER_3];
int rv;
msg_debug("\n");
pmsg_debug("jtag3_edbg_prepare()\n");
if (verbose >= 4)
memset(buf, 0, USBDEV_MAX_XFER_3);
buf[0] = CMSISDAP_CMD_CONNECT;
buf[1] = CMSISDAP_CONN_SWD;
if (serial_send(&pgm->fd, buf, pgm->fd.usb.max_xfer) != 0) {
pmsg_error("unable to send command to serial port\n");
return -1;
}
rv = serial_recv(&pgm->fd, status, pgm->fd.usb.max_xfer);
if (rv != pgm->fd.usb.max_xfer) {
pmsg_error("unable to read from serial port (%d)\n", rv);
return -1;
}
if (status[0] != CMSISDAP_CMD_CONNECT ||
status[1] == 0)
pmsg_error("unexpected response 0x%02x, 0x%02x\n", status[0], status[1]);
pmsg_notice2("jtag3_edbg_prepare(): connection status 0x%02x\n", status[1]);
buf[0] = CMSISDAP_CMD_LED;
buf[1] = CMSISDAP_LED_CONNECT;
buf[2] = 1;
if (serial_send(&pgm->fd, buf, pgm->fd.usb.max_xfer) != 0) {
pmsg_error("unable to send command to serial port\n");
return -1;
}
rv = serial_recv(&pgm->fd, status, pgm->fd.usb.max_xfer);
if (rv != pgm->fd.usb.max_xfer) {
pmsg_error("unable to read from serial port (%d)\n", rv);
return -1;
}
if (status[0] != CMSISDAP_CMD_LED ||
status[1] != 0)
pmsg_error("unexpected response 0x%02x, 0x%02x\n", status[0], status[1]);
return 0;
}
/*
* Send out all the CMSIS-DAP stuff when signing off.
*/
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
static int jtag3_edbg_signoff(const PROGRAMMER *pgm) {
unsigned char buf[USBDEV_MAX_XFER_3];
unsigned char status[USBDEV_MAX_XFER_3];
int rv;
msg_debug("\n");
pmsg_debug("jtag3_edbg_signoff()\n");
if (verbose >= 4)
memset(buf, 0, USBDEV_MAX_XFER_3);
buf[0] = CMSISDAP_CMD_LED;
buf[1] = CMSISDAP_LED_CONNECT;
buf[2] = 0;
if (serial_send(&pgm->fd, buf, pgm->fd.usb.max_xfer) != 0) {
pmsg_notice("jtag3_edbg_signoff(): unable to send command to serial port\n");
return -1;
}
rv = serial_recv(&pgm->fd, status, pgm->fd.usb.max_xfer);
if (rv != pgm->fd.usb.max_xfer) {
pmsg_notice("jtag3_edbg_signoff(): unable to read from serial port (%d)\n", rv);
return -1;
}
if (status[0] != CMSISDAP_CMD_LED ||
status[1] != 0)
pmsg_notice("jtag3_edbg_signoff(): unexpected response 0x%02x, 0x%02x\n", status[0], status[1]);
buf[0] = CMSISDAP_CMD_DISCONNECT;
if (serial_send(&pgm->fd, buf, pgm->fd.usb.max_xfer) != 0) {
pmsg_notice("jtag3_edbg_signoff(): unable to send command to serial port\n");
return -1;
}
rv = serial_recv(&pgm->fd, status, pgm->fd.usb.max_xfer);
if (rv != pgm->fd.usb.max_xfer) {
pmsg_notice("jtag3_edbg_signoff(): unable to read from serial port (%d)\n", rv);
return -1;
}
if (status[0] != CMSISDAP_CMD_DISCONNECT ||
status[1] != 0)
pmsg_notice("jtag3_edbg_signoff(): unexpected response 0x%02x, 0x%02x\n", status[0], status[1]);
return 0;
}
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
static int jtag3_drain(const PROGRAMMER *pgm, int display) {
return serial_drain(&pgm->fd, display);
}
/*
* Receive one frame, return it in *msg. Received sequence number is
* returned in seqno. Any valid frame will be returned, regardless
* whether it matches the expected sequence number, including event
* notification frames (seqno == 0xffff).
*
* Caller must eventually free the buffer.
*/
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
static int jtag3_recv_frame(const PROGRAMMER *pgm, unsigned char **msg) {
int rv;
unsigned char *buf = NULL;
if (pgm->flag & PGM_FL_IS_EDBG)
return jtag3_edbg_recv_frame(pgm, msg);
pmsg_trace("jtag3_recv_frame():\n");
if ((buf = malloc(pgm->fd.usb.max_xfer)) == NULL) {
pmsg_error("out of memory\n");
return -1;
}
if (verbose >= 4)
memset(buf, 0, pgm->fd.usb.max_xfer);
rv = serial_recv(&pgm->fd, buf, pgm->fd.usb.max_xfer);
if (rv < 0) {
/* timeout in receive */
pmsg_notice2("jtag3_recv_frame(): timeout receiving packet\n");
free(buf);
return -1;
}
*msg = buf;
return rv;
}
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
static int jtag3_edbg_recv_frame(const PROGRAMMER *pgm, unsigned char **msg) {
int rv, len = 0;
unsigned char *buf = NULL;
unsigned char *request;
pmsg_trace("jtag3_edbg_recv():\n");
if ((buf = malloc(USBDEV_MAX_XFER_3)) == NULL) {
pmsg_notice("jtag3_edbg_recv(): out of memory\n");
return -1;
}
if ((request = malloc(pgm->fd.usb.max_xfer)) == NULL) {
pmsg_notice("jtag3_edbg_recv(): out of memory\n");
free(buf);
return -1;
}
*msg = buf;
int nfrags = 0;
int thisfrag = 0;
do {
request[0] = EDBG_VENDOR_AVR_RSP;
if (serial_send(&pgm->fd, request, pgm->fd.usb.max_xfer) != 0) {
pmsg_notice("jtag3_edbg_recv(): unable to send CMSIS-DAP vendor command\n");
free(request);
free(*msg);
return -1;
}
rv = serial_recv(&pgm->fd, buf, pgm->fd.usb.max_xfer);
if (rv < 0) {
/* timeout in receive */
pmsg_notice2("jtag3_edbg_recv(): timeout receiving packet\n");
free(*msg);
free(request);
return -1;
}
if (buf[0] != EDBG_VENDOR_AVR_RSP) {
pmsg_notice("jtag3_edbg_recv(): unexpected response 0x%02x\n", buf[0]);
free(*msg);
free(request);
return -1;
}
if (buf[1] == 0) {
// Documentation says:
// "FragmentInfo 0x00 indicates that no response data is
// available, and the rest of the packet is ignored."
pmsg_notice("jtag3_edbg_recv(): no response available\n");
free(*msg);
free(request);
return -1;
}
/* calculate fragment information */
if (thisfrag == 0) {
/* first fragment */
nfrags = buf[1] & 0x0F;
thisfrag = 1;
} else {
if (nfrags != (buf[1] & 0x0F)) {
pmsg_notice("jtag3_edbg_recv(): "
"Inconsistent # of fragments; had %d, now %d\n",
nfrags, (buf[1] & 0x0F));
free(*msg);
free(request);
return -1;
}
}
if (thisfrag != ((buf[1] >> 4) & 0x0F)) {
pmsg_notice("jtag3_edbg_recv(): "
"inconsistent fragment number; expect %d, got %d\n",
thisfrag, ((buf[1] >> 4) & 0x0F));
free(*msg);
free(request);
return -1;
}
int thislen = (buf[2] << 8) | buf[3];
if (thislen > rv + 4) {
pmsg_notice("jtag3_edbg_recv(): unexpected length value (%d > %d)\n", thislen, rv + 4);
thislen = rv + 4;
}
if (len + thislen > USBDEV_MAX_XFER_3) {
pmsg_notice("jtag3_edbg_recv(): length exceeds max size (%d > %d)\n", len + thislen, USBDEV_MAX_XFER_3);
thislen = USBDEV_MAX_XFER_3 - len;
}
memmove(buf, buf + 4, thislen);
thisfrag++;
len += thislen;
buf += thislen;
} while (thisfrag <= nfrags);
free(request);
return len;
}
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
int jtag3_recv(const PROGRAMMER *pgm, unsigned char **msg) {
unsigned short r_seqno;
int rv;
for (;;) {
if ((rv = jtag3_recv_frame(pgm, msg)) <= 0)
return rv;
if ((rv & USB_RECV_FLAG_EVENT) != 0) {
if (verbose >= 3)
jtag3_prevent(pgm, *msg, rv & USB_RECV_LENGTH_MASK);
free(*msg);
continue;
}
rv &= USB_RECV_LENGTH_MASK;
r_seqno = ((*msg)[2] << 8) | (*msg)[1];
pmsg_debug("jtag3_recv(): "
"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;
/*
* We move the payload to the beginning of the buffer, to make
* the job easier for the caller. We have to return the
* original pointer though, as the caller must free() it.
*/
rv -= 3;
if (rv < 0) {
pmsg_error("unexpected return value %d from jtag3_recv_frame()\n", rv);
free(*msg);
return -1;
}
memmove(*msg, *msg + 3, rv);
return rv;
}
pmsg_notice2("jtag3_recv(): "
"got wrong sequence number, %u != %u\n", r_seqno, PDATA(pgm)->command_sequence);
free(*msg);
}
}
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
int jtag3_command(const PROGRAMMER *pgm, unsigned char *cmd, unsigned int cmdlen,
unsigned char **resp, const char *descr) {
int status;
unsigned char c;
pmsg_notice2("sending %s command: ", descr);
jtag3_send(pgm, cmd, cmdlen);
status = jtag3_recv(pgm, resp);
if (status <= 0) {
msg_notice2("\n");
pmsg_notice2("%s command: timeout/error communicating with programmer (status %d)\n", descr, status);
if (status == 0)
free(*resp);
return LIBAVRDUDE_GENERAL_FAILURE;
} else if (verbose >= 3) {
msg_info("\n");
jtag3_prmsg(pgm, *resp, status);
} else {
msg_notice2("0x%02x (%d bytes msg)\n", (*resp)[1], status);
}
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)) {
pmsg_error("device is locked; chip erase required to unlock\n");
} else {
pmsg_notice("bad response to %s command: 0x%02x\n", descr, c);
}
status = (*resp)[3];
free(*resp);
resp = 0;
return jtag3_errcode(status);
}
return status;
}
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
int jtag3_getsync(const PROGRAMMER *pgm, int mode) {
unsigned char buf[3], *resp;
pmsg_debug("jtag3_getsync()\n");
/* XplainedMini boards do not need this, and early revisions had a
* 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;
}
}
/* Get the sign-on information. */
buf[0] = SCOPE_GENERAL;
buf[1] = CMD3_SIGN_ON;
buf[2] = 0;
if (jtag3_command(pgm, buf, 3, &resp, "sign-on") < 0)
return -1;
free(resp);
return 0;
}
/*
* issue the 'chip erase' command to the AVR device
*/
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
static int jtag3_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) {
unsigned char buf[8], *resp;
buf[0] = SCOPE_AVR;
buf[1] = CMD3_ERASE_MEMORY;
buf[2] = 0;
buf[3] = XMEGA_ERASE_CHIP;
buf[4] = buf[5] = buf[6] = buf[7] = 0; /* page address */
if (jtag3_command(pgm, buf, 8, &resp, "chip erase") < 0)
return -1;
free(resp);
return 0;
}
/*
* UPDI 'unlock' -> 'enter progmode' with chip erase key
*/
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
static int jtag3_unlock_erase_key(const PROGRAMMER *pgm, const AVRPART *p) {
unsigned char buf[8], *resp;
buf[0] = 1; /* Enable */
if (jtag3_setparm(pgm, SCOPE_AVR, SET_GET_CTXT_OPTIONS, PARM3_OPT_CHIP_ERASE_TO_ENTER, buf, 1) < 0)
return -1;
buf[0] = SCOPE_AVR;
buf[1] = CMD3_ENTER_PROGMODE;
buf[2] = 0;
if (jtag3_command(pgm, buf, 3, &resp, "enter progmode") < 0)
return -1;
PDATA(pgm)->prog_enabled = 1;
buf[0] = 0; /* Disable */
if (jtag3_setparm(pgm, SCOPE_AVR, SET_GET_CTXT_OPTIONS, PARM3_OPT_CHIP_ERASE_TO_ENTER, buf, 1) < 0)
return -1;
free(resp);
return 0;
}
/*
* There is no chip erase functionality in debugWire mode.
*/
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
static int jtag3_chip_erase_dw(const PROGRAMMER *pgm, const AVRPART *p) {
pmsg_error("chip erase not supported in debugWire mode\n");
return 0;
}
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
static int jtag3_program_enable_dummy(const PROGRAMMER *pgm, const AVRPART *p) {
return 0;
}
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
static int jtag3_program_enable(const PROGRAMMER *pgm) {
unsigned char buf[3], *resp;
int status;
if (PDATA(pgm)->prog_enabled)
return 0;
buf[0] = SCOPE_AVR;
buf[1] = CMD3_ENTER_PROGMODE;
buf[2] = 0;
if ((status = jtag3_command(pgm, buf, 3, &resp, "enter progmode")) >= 0) {
free(resp);
PDATA(pgm)->prog_enabled = 1;
return LIBAVRDUDE_SUCCESS;
}
return status;
}
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
static int jtag3_program_disable(const PROGRAMMER *pgm) {
unsigned char buf[3], *resp;
if (!PDATA(pgm)->prog_enabled)
return 0;
buf[0] = SCOPE_AVR;
buf[1] = CMD3_LEAVE_PROGMODE;
buf[2] = 0;
if (jtag3_command(pgm, buf, 3, &resp, "leave progmode") < 0)
return -1;
free(resp);
PDATA(pgm)->prog_enabled = 0;
return 0;
}
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
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);
}
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
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);
}
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
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);
}
/*
* initialize the AVR device and prepare it to accept commands
*/
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
static int jtag3_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
unsigned char conn = 0, parm[4];
const char *ifname;
unsigned char cmd[4], *resp;
int status;
/*
* At least, as of firmware 2.12, the JTAGICE3 doesn't handle
* splitting packets correctly. On a large transfer, the first
* split packets are correct, but remaining packets contain just
* garbage.
*
* We move the check here so in case future firmware versions fix
* this, the check below can be made dependended on the actual
* firmware level. Retrieving the firmware version can always be
* accomplished with USB 1.1 (64 byte max) packets.
*
* Allow to override the check by -F (so users could try on newer
* firmware), but warn loudly.
*/
if (jtag3_getparm(pgm, SCOPE_GENERAL, 0, PARM3_FW_MAJOR, parm, 2) < 0)
return -1;
if (pgm->fd.usb.max_xfer < USBDEV_MAX_XFER_3 && (pgm->flag & PGM_FL_IS_EDBG) == 0) {
if (ovsigck) {
pmsg_warning("JTAGICE3's firmware %d.%d is broken on USB 1.1 connections\n", parm[0], parm[1]);
imsg_warning("forced to continue by option -F; THIS PUTS THE DEVICE'S DATA INTEGRITY AT RISK!\n");
} else {
pmsg_error("JTAGICE3's firmware %d.%d is broken on USB 1.1 connections\n", parm[0], parm[1]);
return -1;
}
}
if (pgm->flag & PGM_FL_IS_DW) {
ifname = "debugWire";
if (p->prog_modes & PM_debugWIRE)
conn = PARM3_CONN_DW;
} else if (pgm->flag & PGM_FL_IS_PDI) {
ifname = "PDI";
if (p->prog_modes & PM_PDI)
conn = PARM3_CONN_PDI;
} else if (pgm->flag & PGM_FL_IS_UPDI) {
ifname = "UPDI";
if (p->prog_modes & PM_UPDI)
conn = PARM3_CONN_UPDI;
} else {
ifname = "JTAG";
if (p->prog_modes & (PM_JTAG | PM_JTAGmkI | PM_XMEGAJTAG | PM_AVR32JTAG))
conn = PARM3_CONN_JTAG;
}
if (conn == 0) {
pmsg_error("part %s has no %s interface\n", p->desc, ifname);
return -1;
}
if (p->prog_modes & PM_PDI)
parm[0] = PARM3_ARCH_XMEGA;
else if (p->prog_modes & PM_UPDI)
parm[0] = PARM3_ARCH_UPDI;
else if (p->prog_modes & PM_debugWIRE)
parm[0] = PARM3_ARCH_TINY;
else
parm[0] = PARM3_ARCH_MEGA;
if (jtag3_setparm(pgm, SCOPE_AVR, 0, PARM3_ARCH, parm, 1) < 0)
return -1;
parm[0] = PARM3_SESS_PROGRAMMING;
if (jtag3_setparm(pgm, SCOPE_AVR, 0, PARM3_SESS_PURPOSE, parm, 1) < 0)
return -1;
parm[0] = conn;
if (jtag3_setparm(pgm, SCOPE_AVR, 1, PARM3_CONNECTION, parm, 1) < 0)
return -1;
if (conn == PARM3_CONN_PDI || conn == PARM3_CONN_UPDI)
PDATA(pgm)->set_sck = jtag3_set_sck_xmega_pdi;
else if (conn == PARM3_CONN_JTAG) {
if (p->prog_modes & PM_PDI)
PDATA(pgm)->set_sck = jtag3_set_sck_xmega_jtag;
else
PDATA(pgm)->set_sck = jtag3_set_sck_mega_jtag;
}
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);
parm[0] = clock & 0xff;
parm[1] = (clock >> 8) & 0xff;
if (PDATA(pgm)->set_sck(pgm, parm) < 0)
return -1;
}
jtag3_print_parms1(pgm, progbuf, stderr);
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],
PDATA(pgm)->jtagchain[2], PDATA(pgm)->jtagchain[3]);
if (jtag3_setparm(pgm, SCOPE_AVR, 1, PARM3_JTAGCHAIN, PDATA(pgm)->jtagchain, 4) < 0)
return -1;
}
/* set device descriptor data */
if ((p->prog_modes & PM_PDI)) {
struct xmega_device_desc xd;
LNODEID ln;
AVRMEM * m;
u16_to_b2(xd.nvm_base_addr, p->nvm_base);
u16_to_b2(xd.mcu_base_addr, p->mcu_base);
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);
} 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);
} else if (strcmp(m->desc, "application") == 0) {
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);
} else if (strcmp(m->desc, "fuse1") == 0) {
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);
2022-02-28 18:46:47 +00:00
} else if (strcmp(m->desc, "usersig") == 0 ||
strcmp(m->desc, "userrow") == 0) {
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);
} else if (strcmp(m->desc, "data") == 0) {
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)) {
struct updi_device_desc xd;
LNODEID ln;
AVRMEM *m;
u16_to_b2(xd.nvm_base_addr, p->nvm_base);
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)) {
m = ldata(ln);
if (strcmp(m->desc, "flash") == 0) {
u16_to_b2(xd.prog_base, m->offset&0xFFFF);
xd.prog_base_msb = m->offset>>16;
if (m->readsize != 0 && m->readsize < m->page_size)
PDATA(pgm)->flash_pagesize = m->readsize;
else
PDATA(pgm)->flash_pagesize = m->page_size;
xd.flash_page_size = m->page_size & 0xFF;
xd.flash_page_size_msb = (m->page_size)>>8;
u32_to_b4(xd.flash_bytes, m->size);
if (m->offset > 0xFFFF)
xd.address_mode = UPDI_ADDRESS_MODE_24BIT;
else
xd.address_mode = UPDI_ADDRESS_MODE_16BIT;
}
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_bytes, m->size);
u16_to_b2(xd.eeprom_base, m->offset);
}
2022-02-28 18:46:47 +00:00
else if (strcmp(m->desc, "usersig") == 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) {
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) {
xd.fuses_bytes = m->size;
u16_to_b2(xd.fuses_base, m->offset);
}
else if (strcmp(m->desc, "lock") == 0) {
u16_to_b2(xd.lockbits_base, m->offset);
}
}
// Generate UPDI high-voltage pulse if user asks for it and hardware supports it
if (p->prog_modes & PM_UPDI &&
PDATA(pgm)->use_hvupdi == true &&
p->hvupdi_variant != HV_UPDI_VARIANT_1) {
parm[0] = PARM3_UPDI_HV_NONE;
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");
parm[0] = PARM3_UPDI_HV_SIMPLE_PULSE;
break;
}
}
if (parm[0] == PARM3_UPDI_HV_NONE) {
pmsg_error("%s does not support sending HV pulse to target %s\n", pgm->desc, p->desc);
return -1;
}
if (jtag3_setparm(pgm, SCOPE_AVR, 3, PARM3_OPT_12V_UPDI_ENABLE, parm, 1) < 0)
return -1;
}
2022-06-29 17:55:23 +00:00
u16_to_b2(xd.default_min_div1_voltage, DEFAULT_MINIMUM_CHARACTERISED_DIV1_VOLTAGE_MV);
u16_to_b2(xd.default_min_div2_voltage, DEFAULT_MINIMUM_CHARACTERISED_DIV2_VOLTAGE_MV);
u16_to_b2(xd.default_min_div4_voltage, DEFAULT_MINIMUM_CHARACTERISED_DIV4_VOLTAGE_MV);
u16_to_b2(xd.default_min_div8_voltage, DEFAULT_MINIMUM_CHARACTERISED_DIV8_VOLTAGE_MV);
u16_to_b2(xd.pdi_pad_fmax, MAX_FREQUENCY_SHARED_UPDI_PIN);
xd.syscfg_offset = FUSES_SYSCFG0_OFFSET;
xd.syscfg_write_mask_and = 0xFF;
xd.syscfg_write_mask_or = 0x00;
xd.syscfg_erase_mask_and = 0xFF;
xd.syscfg_erase_mask_or = 0x00;
msg_notice2("UPDI SET: \n\t"
"xd->prog_base_msb=%x\n\t"
"xd->prog_base=%x %x\n\t"
"xd->flash_page_size_msb=%x\n\t"
"xd->flash_page_size=%x\n\t"
"xd->eeprom_page_size=%x\n\t"
"xd->nvmctrl=%x %x\n\t"
"xd->ocd=%x %x\n\t"
"xd->address_mode=%x\n",
xd.prog_base_msb,
xd.prog_base[0], xd.prog_base[1],
xd.flash_page_size_msb,
xd.flash_page_size,
xd.eeprom_page_size,
xd.nvm_base_addr[0], xd.nvm_base_addr[1],
xd.ocd_base_addr[0], xd.ocd_base_addr[1],
xd.address_mode);
if (jtag3_setparm(pgm, SCOPE_AVR, 2, PARM3_DEVICEDESC, (unsigned char *)&xd, sizeof xd) < 0)
return -1;
}
else {
struct mega_device_desc md;
LNODEID ln;
AVRMEM * m;
unsigned int flashsize = 0;
memset(&md, 0, sizeof md);
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);
} 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);
}
}
u16_to_b2(md.sram_offset, 0x100); // do we need it? YES, but it won't be used
if (p->ocdrev == -1) {
int ocdrev;
/* lacking a proper definition, guess the OCD revision */
if (p->prog_modes & PM_debugWIRE)
ocdrev = 1; /* exception: ATtiny13, 2313, 4313 */
else if (flashsize > 128 * 1024)
ocdrev = 4;
else
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 {
md.ocd_revision = p->ocdrev;
}
md.always_one = 1;
md.allow_full_page_bitstream = (p->flags & AVRPART_ALLOWFULLPAGEBITSTREAM) != 0;
md.idr_address = p->idr;
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
unsigned char eecr = p->eecr? p->eecr: 0x3f; // Use default 0x3f if not set
md.eearh_address = eecr - 0x20 + 3;
md.eearl_address = eecr - 0x20 + 2;
md.eecr_address = eecr - 0x20;
md.eedr_address = eecr - 0x20 + 1;
md.spmcr_address = p->spmcr;
//md.osccal_address = p->osccal; // do we need it at all?
if (jtag3_setparm(pgm, SCOPE_AVR, 2, PARM3_DEVICEDESC, (unsigned char *)&md, sizeof md) < 0)
return -1;
}
int use_ext_reset;
for (use_ext_reset = 0; use_ext_reset <= 1; use_ext_reset++) {
cmd[0] = SCOPE_AVR;
cmd[1] = CMD3_SIGN_ON;
cmd[2] = 0;
cmd[3] = use_ext_reset; /* external reset */
if ((status = jtag3_command(pgm, cmd, 4, &resp, "AVR sign-on")) >= 0)
break;
pmsg_notice("retrying with external reset applied\n");
}
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;
}
/*
* Depending on the target connection, there are three different
* possible replies of the ICE. For a JTAG connection, the reply
* format is RSP3_DATA, followed by 4 bytes of the JTAG ID read from
* the device (followed by a trailing 0).
* For a UPDI connection the reply format is RSP3_DATA, followed by
* 4 bytes of the SIB Family_ID read from the device (followed by a
* trailing 0).
* For all other connections
* (except ISP which is handled completely differently, but that
* doesn't apply here anyway), the response is just RSP_OK.
*/
if (resp[1] == RSP3_DATA && status >= 7) {
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]);
}
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]);
}
free(resp);
PDATA(pgm)->boot_start = ULONG_MAX;
if (p->prog_modes & PM_PDI) {
// Find the border between application and boot area
AVRMEM *bootmem = avr_locate_mem(p, "boot");
AVRMEM *flashmem = avr_locate_mem(p, "flash");
if (bootmem == NULL || flashmem == NULL) {
pmsg_error("cannot locate flash or boot memories in description\n");
} else {
PDATA(pgm)->boot_start = bootmem->offset - flashmem->offset;
}
}
free(PDATA(pgm)->flash_pagecache);
free(PDATA(pgm)->eeprom_pagecache);
if ((PDATA(pgm)->flash_pagecache = malloc(PDATA(pgm)->flash_pagesize)) == NULL) {
pmsg_error("out of memory\n");
return -1;
}
if ((PDATA(pgm)->eeprom_pagecache = malloc(PDATA(pgm)->eeprom_pagesize)) == NULL) {
pmsg_error("out of memory\n");
free(PDATA(pgm)->flash_pagecache);
return -1;
}
PDATA(pgm)->flash_pageaddr = PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L;
return 0;
}
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
static void jtag3_disable(const PROGRAMMER *pgm) {
free(PDATA(pgm)->flash_pagecache);
PDATA(pgm)->flash_pagecache = NULL;
free(PDATA(pgm)->eeprom_pagecache);
PDATA(pgm)->eeprom_pagecache = NULL;
/*
* jtag3_program_disable() doesn't do anything if the
* device is currently not in programming mode, so just
* call it unconditionally here.
*/
(void)jtag3_program_disable(pgm);
}
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
static void jtag3_enable(PROGRAMMER *pgm, const AVRPART *p) {
return;
}
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
static int jtag3_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) {
LNODEID ln;
const char *extended_param;
int rv = 0;
for (ln = lfirst(extparms); ln; ln = lnext(ln)) {
extended_param = ldata(ln);
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) {
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);
PDATA(pgm)->jtagchain[0] = ub;
PDATA(pgm)->jtagchain[1] = ua;
PDATA(pgm)->jtagchain[2] = bb;
PDATA(pgm)->jtagchain[3] = ba;
continue;
}
else if ((strcmp(extended_param, "hvupdi") == 0) &&
(lsize(pgm->hvupdi_support) > 1)) {
PDATA(pgm)->use_hvupdi = true;
continue;
}
pmsg_error("invalid extended parameter '%s'\n", extended_param);
rv = -1;
}
return rv;
}
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
int jtag3_open_common(PROGRAMMER *pgm, const char *port) {
union pinfo pinfo;
LNODEID usbpid;
int rv = -1;
#if !defined(HAVE_LIBUSB) && !defined(HAVE_LIBHIDAPI)
pmsg_error("was compiled without USB or HIDAPI support\n");
return -1;
#endif
if (!matches(port, "usb")) {
pmsg_error("JTAGICE3/EDBG port names must start with usb\n");
return -1;
}
if (pgm->usbvid)
pinfo.usbinfo.vid = pgm->usbvid;
else
pinfo.usbinfo.vid = USB_VENDOR_ATMEL;
/* If the config entry did not specify a USB PID, insert the default one. */
if (lfirst(pgm->usbpid) == NULL)
ladd(pgm->usbpid, (void *)USB_DEVICE_JTAGICE3);
#if defined(HAVE_LIBHIDAPI)
/*
* Try HIDAPI first. LibUSB is more generic, but might then cause
* troubles for HID-class devices in some OSes (like Windows).
*/
serdev = &usbhid_serdev;
for (usbpid = lfirst(pgm->usbpid); rv < 0 && usbpid != NULL; usbpid = lnext(usbpid)) {
pinfo.usbinfo.flags = PINFO_FL_SILENT;
pinfo.usbinfo.pid = *(int *)(ldata(usbpid));
pgm->fd.usb.max_xfer = USBDEV_MAX_XFER_3;
pgm->fd.usb.rep = USBDEV_BULK_EP_READ_3;
pgm->fd.usb.wep = USBDEV_BULK_EP_WRITE_3;
pgm->fd.usb.eep = 0;
strcpy(pgm->port, port);
rv = serial_open(port, pinfo, &pgm->fd);
}
if (rv < 0) {
#endif /* HAVE_LIBHIDAPI */
#if defined(HAVE_LIBUSB)
serdev = &usb_serdev_frame;
for (usbpid = lfirst(pgm->usbpid); rv < 0 && usbpid != NULL; usbpid = lnext(usbpid)) {
pinfo.usbinfo.flags = PINFO_FL_SILENT;
pinfo.usbinfo.pid = *(int *)(ldata(usbpid));
pgm->fd.usb.max_xfer = USBDEV_MAX_XFER_3;
pgm->fd.usb.rep = USBDEV_BULK_EP_READ_3;
pgm->fd.usb.wep = USBDEV_BULK_EP_WRITE_3;
pgm->fd.usb.eep = USBDEV_EVT_EP_READ_3;
strcpy(pgm->port, port);
rv = serial_open(port, pinfo, &pgm->fd);
}
#endif /* HAVE_LIBUSB */
#if defined(HAVE_LIBHIDAPI)
}
#endif
if (rv < 0) {
2022-10-19 22:13:37 +00:00
// Check if SNAP or PICkit4 is in PIC mode
for(LNODEID ln=lfirst(pgm->id); ln; ln=lnext(ln)) {
if (matches(ldata(ln), "snap")) {
pinfo.usbinfo.vid = USB_VENDOR_MICROCHIP;
pinfo.usbinfo.pid = USB_DEVICE_SNAP_PIC_MODE;
int pic_mode = serial_open(port, pinfo, &pgm->fd);
if(pic_mode < 0) {
// Retry with alternative USB PID
pinfo.usbinfo.pid = USB_DEVICE_SNAP_PIC_MODE_ALT;
pic_mode = serial_open(port, pinfo, &pgm->fd);
}
2022-10-19 22:13:37 +00:00
if(pic_mode >= 0) {
msg_error("\n");
pmsg_error("MPLAB SNAP in PIC mode detected!\n");
imsg_error("Use MPLAB X or Microchip Studio to switch to AVR mode\n\n");
return -1;
}
} else if(matches(ldata(ln), "pickit4")) {
pinfo.usbinfo.vid = USB_VENDOR_MICROCHIP;
pinfo.usbinfo.pid = USB_DEVICE_PICKIT4_PIC_MODE;
int pic_mode = serial_open(port, pinfo, &pgm->fd);
if(pic_mode < 0) {
// Retry with alternative USB PID
pinfo.usbinfo.pid = USB_DEVICE_PICKIT4_PIC_MODE_ALT;
pic_mode = serial_open(port, pinfo, &pgm->fd);
}
2022-10-19 22:13:37 +00:00
if(pic_mode >= 0) {
msg_error("\n");
pmsg_error("PICkit4 in PIC mode detected!\n");
imsg_error("Use MPLAB X or Microchip Studio to switch to AVR mode\n\n");
return -1;
}
}
}
pmsg_error("no device found matching VID 0x%04x and PID list: ",
(unsigned) pinfo.usbinfo.vid);
int notfirst = 0;
for (usbpid = lfirst(pgm->usbpid); usbpid != NULL; usbpid = lnext(usbpid)) {
if (notfirst)
msg_error(", ");
msg_error("0x%04x", (unsigned int)(*(int *)(ldata(usbpid))));
notfirst = 1;
}
char *serno;
if ((serno = strchr(port, ':')))
msg_error(" with SN %s", ++serno);
msg_error("\n");
return -1;
}
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;
pmsg_notice("found CMSIS-DAP compliant device, using EDBG protocol\n");
}
2023-01-02 17:10:15 +00:00
// Make USB serial number available to programmer
if (serdev && serdev->usbsn)
pgm->usbsn = serdev->usbsn;
/*
* drain any extraneous input
*/
jtag3_drain(pgm, 0);
return 0;
}
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
static int jtag3_open(PROGRAMMER *pgm, const char *port) {
pmsg_notice2("jtag3_open()\n");
if (jtag3_open_common(pgm, port) < 0)
return -1;
if (jtag3_getsync(pgm, PARM3_CONN_JTAG) < 0)
return -1;
return 0;
}
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
static int jtag3_open_dw(PROGRAMMER *pgm, const char *port) {
pmsg_notice2("jtag3_open_dw()\n");
if (jtag3_open_common(pgm, port) < 0)
return -1;
if (jtag3_getsync(pgm, PARM3_CONN_DW) < 0)
return -1;
return 0;
}
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
static int jtag3_open_pdi(PROGRAMMER *pgm, const char *port) {
pmsg_notice2("jtag3_open_pdi()\n");
if (jtag3_open_common(pgm, port) < 0)
return -1;
if (jtag3_getsync(pgm, PARM3_CONN_PDI) < 0)
return -1;
return 0;
}
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
static int jtag3_open_updi(PROGRAMMER *pgm, const char *port) {
pmsg_notice2("jtag3_open_updi()\n");
LNODEID ln;
pmsg_notice2("HV UPDI support:");
for (ln = lfirst(pgm->hvupdi_support); ln; ln = lnext(ln))
msg_notice2(" %d", *(int *) ldata(ln));
msg_notice2("\n");
if (jtag3_open_common(pgm, port) < 0)
return -1;
if (jtag3_getsync(pgm, PARM3_CONN_UPDI) < 0)
return -1;
return 0;
}
void jtag3_close(PROGRAMMER * pgm) {
unsigned char buf[4], *resp;
pmsg_notice2("jtag3_close()\n");
buf[0] = SCOPE_AVR;
buf[1] = CMD3_SIGN_OFF;
buf[2] = buf[3] = 0;
if (jtag3_command(pgm, buf, 3, &resp, "AVR sign-off") >= 0)
free(resp);
buf[0] = SCOPE_GENERAL;
buf[1] = CMD3_SIGN_OFF;
if (jtag3_command(pgm, buf, 4, &resp, "sign-off") >= 0)
free(resp);
/* XplainedMini boards do not need this, and early revisions had a
* firmware bug where they complained about it. */
if ((pgm->flag & PGM_FL_IS_EDBG) &&
!matches(ldata(lfirst(pgm->id)), "xplainedmini")) {
jtag3_edbg_signoff(pgm);
}
serial_close(&pgm->fd);
pgm->fd.ifd = -1;
}
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
static int jtag3_page_erase(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
unsigned int addr) {
unsigned char cmd[8], *resp;
pmsg_notice2("jtag3_page_erase(.., %s, 0x%x)\n", m->desc, addr);
if (!(p->prog_modes & (PM_PDI | PM_UPDI))) {
pmsg_error("page erase not supported\n");
return -1;
}
if (jtag3_program_enable(pgm) < 0)
return -1;
cmd[0] = SCOPE_AVR;
cmd[1] = CMD3_ERASE_MEMORY;
cmd[2] = 0;
if (avr_mem_is_flash_type(m)) {
if (p->prog_modes & PM_UPDI || jtag3_memtype(pgm, p, addr) == MTYPE_FLASH)
cmd[3] = XMEGA_ERASE_APP_PAGE;
else
cmd[3] = XMEGA_ERASE_BOOT_PAGE;
} else if (strcmp(m->desc, "eeprom") == 0) {
cmd[3] = XMEGA_ERASE_EEPROM_PAGE;
2022-02-28 18:46:47 +00:00
} else if (strcmp(m->desc, "usersig") == 0 ||
strcmp(m->desc, "userrow") == 0) {
cmd[3] = XMEGA_ERASE_USERSIG;
} else {
cmd[3] = XMEGA_ERASE_APP_PAGE;
}
unsigned int addr_adj = addr;
if(p->prog_modes & PM_PDI)
addr_adj += m->offset;
else // PM_UPDI
addr_adj = jtag3_memaddr(pgm, p, m, addr);
u32_to_b4(cmd + 4, addr_adj);
if (jtag3_command(pgm, cmd, 8, &resp, "page erase") < 0)
return -1;
free(resp);
return 0;
}
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
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 block_size;
unsigned int maxaddr = addr + n_bytes;
unsigned char *cmd;
unsigned char *resp;
int status, dynamic_memtype = 0;
long otimeout = serial_recv_timeout;
pmsg_notice2("jtag3_paged_write(.., %s, %d, 0x%04x, %d)\n", m->desc, page_size, addr, n_bytes);
block_size = jtag3_memaddr(pgm, p, m, addr);
if(block_size != addr)
msg_notice2(" mapped to address: 0x%04x\n", block_size);
block_size = 0;
if (!(pgm->flag & PGM_FL_IS_DW) && jtag3_program_enable(pgm) < 0)
return -1;
if (page_size == 0)
page_size = 256;
if ((cmd = malloc(page_size + 13)) == NULL) {
pmsg_error("out of memory\n");
return -1;
}
cmd[0] = SCOPE_AVR;
cmd[1] = CMD3_WRITE_MEMORY;
cmd[2] = 0;
if (strcmp(m->desc, "flash") == 0) {
PDATA(pgm)->flash_pageaddr = (unsigned long)-1L;
cmd[3] = jtag3_memtype(pgm, p, addr);
if (p->prog_modes & PM_PDI)
/* dynamically decide between flash/boot memtype */
dynamic_memtype = 1;
} else if (strcmp(m->desc, "eeprom") == 0) {
if (pgm->flag & PGM_FL_IS_DW) {
/*
* jtag3_paged_write() to EEPROM attempted while in
* 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;
}
}
free(cmd);
return n_bytes;
}
cmd[3] = p->prog_modes & (PM_PDI | PM_UPDI)? MTYPE_EEPROM_XMEGA: MTYPE_EEPROM_PAGE;
PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L;
2022-02-28 18:46:47 +00:00
} else if (strcmp(m->desc, "usersig") == 0 ||
strcmp(m->desc, "userrow") == 0) {
cmd[3] = MTYPE_USERSIG;
2022-02-28 18:46:47 +00:00
} else if (strcmp(m->desc, "boot") == 0) {
cmd[3] = MTYPE_BOOT_FLASH;
} else if (p->prog_modes & (PM_PDI | PM_UPDI)) {
cmd[3] = MTYPE_FLASH;
} else {
cmd[3] = MTYPE_SPM;
}
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 %d is %d\n", addr, block_size);
if (dynamic_memtype)
cmd[3] = jtag3_memtype(pgm, p, addr);
u32_to_b4(cmd + 8, page_size);
u32_to_b4(cmd + 4, jtag3_memaddr(pgm, p, m, addr));
cmd[12] = 0;
/*
* The JTAG ICE will refuse to write anything but a full page, at
* least for the flash ROM. 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 + 13, 0xff, page_size);
memcpy(cmd + 13, m->buf + addr, block_size);
if ((status = jtag3_command(pgm, cmd, page_size + 13,
&resp, "write memory")) < 0) {
free(cmd);
serial_recv_timeout = otimeout;
return -1;
}
free(resp);
}
free(cmd);
serial_recv_timeout = otimeout;
return n_bytes;
}
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
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 block_size;
unsigned int maxaddr = addr + n_bytes;
unsigned char cmd[12];
unsigned char *resp;
int status, dynamic_memtype = 0;
long otimeout = serial_recv_timeout;
pmsg_notice2("jtag3_paged_load(.., %s, %d, 0x%04x, %d)\n",
m->desc, page_size, addr, n_bytes);
block_size = jtag3_memaddr(pgm, p, m, addr);
if(block_size != addr)
msg_notice2(" mapped to address: 0x%04x\n", block_size);
block_size = 0;
if (!(pgm->flag & PGM_FL_IS_DW) && jtag3_program_enable(pgm) < 0)
return -1;
page_size = m->readsize;
cmd[0] = SCOPE_AVR;
cmd[1] = CMD3_READ_MEMORY;
cmd[2] = 0;
if (strcmp(m->desc, "flash") == 0) {
cmd[3] = jtag3_memtype(pgm, p, addr);
if (p->prog_modes & PM_PDI)
/* dynamically decide between flash/boot memtype */
dynamic_memtype = 1;
} else if (strcmp(m->desc, "eeprom") == 0) {
cmd[3] = p->prog_modes & (PM_PDI | PM_UPDI)? MTYPE_EEPROM: MTYPE_EEPROM_PAGE;
if (pgm->flag & PGM_FL_IS_DW)
return -1;
2022-02-28 18:46:47 +00:00
} else if (strcmp(m->desc, "prodsig") == 0) {
cmd[3] = MTYPE_PRODSIG;
2022-02-28 18:46:47 +00:00
} else if (strcmp(m->desc, "usersig") == 0 ||
strcmp(m->desc, "userrow") == 0) {
cmd[3] = MTYPE_USERSIG;
2022-02-28 18:46:47 +00:00
} else if (strcmp(m->desc, "boot") == 0) {
cmd[3] = MTYPE_BOOT_FLASH;
} else if (p->prog_modes & PM_PDI) {
cmd[3] = MTYPE_FLASH;
} else if (p->prog_modes & PM_UPDI) {
cmd[3] = MTYPE_SRAM;
} else {
cmd[3] = MTYPE_SPM;
}
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(): "
"block_size at addr %d is %d\n", addr, block_size);
if (dynamic_memtype)
cmd[3] = jtag3_memtype(pgm, p, addr);
u32_to_b4(cmd + 8, block_size);
u32_to_b4(cmd + 4, jtag3_memaddr(pgm, p, m, addr));
if ((status = jtag3_command(pgm, cmd, 12, &resp, "read memory")) < 0)
return -1;
if (resp[1] != RSP3_DATA || status < (int) block_size + 4) {
pmsg_error("wrong/short reply to read memory command\n");
serial_recv_timeout = otimeout;
free(resp);
return -1;
}
if(status < 4) {
pmsg_error("unexpected response from read memory jtag3_command()\n");
free(resp);
return -1;
}
memcpy(m->buf + addr, resp + 3, status - 4);
free(resp);
}
serial_recv_timeout = otimeout;
return n_bytes;
}
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
static int jtag3_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
unsigned long addr, unsigned char * value) {
unsigned char cmd[12];
unsigned char *resp, *cache_ptr = NULL;
int status, unsupp = 0;
unsigned long paddr = 0UL, *paddr_ptr = NULL;
unsigned int pagesize = 0;
pmsg_notice2("jtag3_read_byte(.., %s, 0x%lx, ...)\n", mem->desc, addr);
paddr = jtag3_memaddr(pgm, p, mem, addr);
if(paddr != addr)
msg_notice2(" mapped to address: 0x%lx\n", paddr);
paddr = 0;
if (!(pgm->flag & PGM_FL_IS_DW))
if ((status = jtag3_program_enable(pgm)) < 0)
return status;
cmd[0] = SCOPE_AVR;
cmd[1] = CMD3_READ_MEMORY;
cmd[2] = 0;
cmd[3] = p->prog_modes & (PM_PDI | PM_UPDI)? MTYPE_FLASH: MTYPE_FLASH_PAGE;
if (avr_mem_is_flash_type(mem)) {
addr += mem->offset & (512 * 1024 - 1); /* max 512 KiB flash */
pagesize = PDATA(pgm)->flash_pagesize;
paddr = addr & ~(pagesize - 1);
paddr_ptr = &PDATA(pgm)->flash_pageaddr;
cache_ptr = PDATA(pgm)->flash_pagecache;
} else if (avr_mem_is_eeprom_type(mem)) {
if ( (pgm->flag & PGM_FL_IS_DW) || (p->prog_modes & PM_PDI) || (p->prog_modes & PM_UPDI) ) {
cmd[3] = MTYPE_EEPROM;
} else {
cmd[3] = MTYPE_EEPROM_PAGE;
}
pagesize = mem->page_size;
paddr = addr & ~(pagesize - 1);
paddr_ptr = &PDATA(pgm)->eeprom_pageaddr;
cache_ptr = PDATA(pgm)->eeprom_pagecache;
} else if (strcmp(mem->desc, "lfuse") == 0) {
cmd[3] = MTYPE_FUSE_BITS;
addr = 0;
if (pgm->flag & PGM_FL_IS_DW)
unsupp = 1;
} else if (strcmp(mem->desc, "hfuse") == 0) {
cmd[3] = MTYPE_FUSE_BITS;
addr = 1;
if (pgm->flag & PGM_FL_IS_DW)
unsupp = 1;
} else if (strcmp(mem->desc, "efuse") == 0) {
cmd[3] = MTYPE_FUSE_BITS;
addr = 2;
if (pgm->flag & PGM_FL_IS_DW)
unsupp = 1;
} else if (matches(mem->desc, "lock")) {
cmd[3] = MTYPE_LOCK_BITS;
if (pgm->flag & PGM_FL_IS_DW)
unsupp = 1;
} else if (matches(mem->desc, "fuse")) {
cmd[3] = MTYPE_FUSE_BITS;
if (!(p->prog_modes & PM_UPDI))
addr = mem->offset & 7;
2022-02-28 18:46:47 +00:00
} else if (strcmp(mem->desc, "usersig") == 0 ||
strcmp(mem->desc, "userrow") == 0) {
cmd[3] = MTYPE_USERSIG;
} else if (strcmp(mem->desc, "prodsig") == 0) {
cmd[3] = MTYPE_PRODSIG;
} else if (strcmp(mem->desc, "sernum") == 0) {
cmd[3] = MTYPE_SIGN_JTAG;
} else if (strcmp(mem->desc, "osccal16") == 0) {
cmd[3] = MTYPE_SIGN_JTAG;
} else if (strcmp(mem->desc, "osccal20") == 0) {
cmd[3] = MTYPE_SIGN_JTAG;
} else if (strcmp(mem->desc, "tempsense") == 0) {
cmd[3] = MTYPE_SIGN_JTAG;
} else if (strcmp(mem->desc, "osc16err") == 0) {
cmd[3] = MTYPE_SIGN_JTAG;
} else if (strcmp(mem->desc, "osc20err") == 0) {
cmd[3] = MTYPE_SIGN_JTAG;
} else if (strcmp(mem->desc, "calibration") == 0) {
cmd[3] = MTYPE_OSCCAL_BYTE;
if (pgm->flag & PGM_FL_IS_DW)
unsupp = 1;
} else if (strcmp(mem->desc, "signature") == 0) {
static unsigned char signature_cache[2];
cmd[3] = MTYPE_SIGN_JTAG;
/*
* dW can read out the signature on JTAGICE3, but only allows
* for a full three-byte read. We cache them in a local
* variable to avoid multiple reads. This optimization does not
* harm for other connection types either.
*/
u32_to_b4(cmd + 8, 3);
u32_to_b4(cmd + 4, jtag3_memaddr(pgm, p, mem, addr));
if (addr == 0) {
if ((status = jtag3_command(pgm, cmd, 12, &resp, "read memory")) < 0)
return status;
signature_cache[0] = resp[4];
signature_cache[1] = resp[5];
*value = resp[3];
free(resp);
return 0;
} else if (addr <= 2) {
*value = signature_cache[addr - 1];
return 0;
} else {
/* should not happen */
msg_error("address out of range for signature memory: %lu\n", addr);
return -1;
}
}
/*
* If the respective memory area is not supported under debugWire,
* leave here.
*/
if (unsupp) {
*value = 42;
return -1;
}
/*
* To improve the read speed, we used paged reads for flash and
* EEPROM, and cache the results in a page cache.
*
* Page cache validation is based on "{flash,eeprom}_pageaddr"
* (holding the base address of the most recent cache fill
* operation). This variable is set to (unsigned long)-1L when the
* cache needs to be invalidated.
*/
if (pagesize && paddr == *paddr_ptr) {
*value = cache_ptr[addr & (pagesize - 1)];
return 0;
}
if (pagesize) {
u32_to_b4(cmd + 8, pagesize);
u32_to_b4(cmd + 4, jtag3_memaddr(pgm, p, mem, paddr));
} else {
u32_to_b4(cmd + 8, 1);
u32_to_b4(cmd + 4, jtag3_memaddr(pgm, p, mem, addr));
}
if ((status = jtag3_command(pgm, cmd, 12, &resp, "read memory")) < 0)
return status;
if (resp[1] != RSP3_DATA ||
status < (int) (pagesize? pagesize: 1) + 4) {
pmsg_error("wrong/short reply to read memory command\n");
free(resp);
return -1;
}
if (pagesize) {
*paddr_ptr = paddr;
memcpy(cache_ptr, resp + 3, pagesize);
*value = cache_ptr[addr & (pagesize - 1)];
} else
*value = resp[3];
free(resp);
return 0;
}
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
static int jtag3_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
unsigned long addr, unsigned char data) {
unsigned char cmd[14];
unsigned char *resp;
unsigned char *cache_ptr = 0;
int status, unsupp = 0;
unsigned int pagesize = 0;
unsigned long mapped_addr;
pmsg_notice2("jtag3_write_byte(.., %s, 0x%lx, ...)\n", mem->desc, addr);
mapped_addr = jtag3_memaddr(pgm, p, mem, addr);
if(mapped_addr != addr)
msg_notice2(" mapped to address: 0x%lx\n", mapped_addr);
cmd[0] = SCOPE_AVR;
cmd[1] = CMD3_WRITE_MEMORY;
cmd[2] = 0;
cmd[3] = p->prog_modes & (PM_PDI | PM_UPDI)? MTYPE_FLASH: MTYPE_SPM;
if (strcmp(mem->desc, "flash") == 0) {
cache_ptr = PDATA(pgm)->flash_pagecache;
pagesize = PDATA(pgm)->flash_pagesize;
PDATA(pgm)->flash_pageaddr = (unsigned long)-1L;
if (pgm->flag & PGM_FL_IS_DW)
unsupp = 1;
} else if (strcmp(mem->desc, "eeprom") == 0) {
if (pgm->flag & PGM_FL_IS_DW) {
cmd[3] = MTYPE_EEPROM;
} else {
cache_ptr = PDATA(pgm)->eeprom_pagecache;
pagesize = PDATA(pgm)->eeprom_pagesize;
}
PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L;
} else if (strcmp(mem->desc, "lfuse") == 0) {
cmd[3] = MTYPE_FUSE_BITS;
addr = 0;
if (pgm->flag & PGM_FL_IS_DW)
unsupp = 1;
} else if (strcmp(mem->desc, "hfuse") == 0) {
cmd[3] = MTYPE_FUSE_BITS;
addr = 1;
if (pgm->flag & PGM_FL_IS_DW)
unsupp = 1;
} else if (strcmp(mem->desc, "efuse") == 0) {
cmd[3] = MTYPE_FUSE_BITS;
addr = 2;
if (pgm->flag & PGM_FL_IS_DW)
unsupp = 1;
} else if (matches(mem->desc, "fuse")) {
cmd[3] = MTYPE_FUSE_BITS;
if (!(p->prog_modes & PM_UPDI))
addr = mem->offset & 7;
2022-02-28 18:46:47 +00:00
} else if (strcmp(mem->desc, "usersig") == 0 ||
strcmp(mem->desc, "userrow") == 0) {
cmd[3] = MTYPE_USERSIG;
} else if (strcmp(mem->desc, "prodsig") == 0) {
cmd[3] = MTYPE_PRODSIG;
} else if (matches(mem->desc, "lock")) {
cmd[3] = MTYPE_LOCK_BITS;
if (pgm->flag & PGM_FL_IS_DW)
unsupp = 1;
} else if (strcmp(mem->desc, "calibration") == 0) {
cmd[3] = MTYPE_OSCCAL_BYTE;
if (pgm->flag & PGM_FL_IS_DW)
unsupp = 1;
} else if (strcmp(mem->desc, "signature") == 0) {
cmd[3] = MTYPE_SIGN_JTAG;
if (pgm->flag & PGM_FL_IS_DW)
unsupp = 1;
}
if (unsupp)
return -1;
if (pagesize != 0) {
/* flash or EEPROM write: use paged algorithm */
unsigned char dummy;
int i;
/* step #1: ensure the page cache is up to date */
if (jtag3_read_byte(pgm, p, mem, addr, &dummy) < 0)
return -1;
/* 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 */
memcpy(mem->buf + addr, cache_ptr, pagesize);
/* step #3: write back */
i = jtag3_paged_write(pgm, p, mem, pagesize, addr, pagesize);
if (i < 0)
return -1;
else
return 0;
}
/* non-paged writes go here */
if (!(pgm->flag & PGM_FL_IS_DW) && jtag3_program_enable(pgm) < 0)
return -1;
u32_to_b4(cmd + 8, 1);
u32_to_b4(cmd + 4, jtag3_memaddr(pgm, p, mem, addr));
cmd[12] = 0;
cmd[13] = data;
if ((status = jtag3_command(pgm, cmd, 14, &resp, "write memory")) < 0)
return status;
free(resp);
return 0;
}
/*
* Set the JTAG clock. The actual frequency is quite a bit of
* guesswork, based on the values claimed by AVR Studio. Inside the
* JTAG ICE, the value is the delay count of a delay loop between the
* JTAG clock edges. A count of 0 bypasses the delay loop.
*
* As the STK500 expresses it as a period length (and we actualy do
* program a period length as well), we rather call it by that name.
*/
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
static int jtag3_set_sck_period(const PROGRAMMER *pgm, double v) {
unsigned char parm[2];
unsigned int clock = 1E-3 / v; /* kHz */
parm[0] = clock & 0xff;
parm[1] = (clock >> 8) & 0xff;
if (PDATA(pgm)->set_sck == NULL) {
pmsg_error("no backend to set the SCK period for\n");
return -1;
}
return (PDATA(pgm)->set_sck(pgm, parm) < 0)? -1: 0;
}
/*
* Read (an) emulator parameter(s).
*/
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
int jtag3_getparm(const PROGRAMMER *pgm, unsigned char scope,
unsigned char section, unsigned char parm,
unsigned char *value, unsigned char length) {
int status;
unsigned char buf[6], *resp, c;
char descr[60];
pmsg_notice2("jtag3_getparm()\n");
buf[0] = scope;
buf[1] = CMD3_GET_PARAMETER;
buf[2] = 0;
buf[3] = section;
buf[4] = parm;
buf[5] = length;
sprintf(descr, "get parameter (scope 0x%02x, section %d, parm %d)",
scope, section, parm);
if ((status = jtag3_command(pgm, buf, 6, &resp, descr)) < 0)
return -1;
c = resp[1];
if (c != RSP3_DATA || status < 3) {
pmsg_notice("jtag3_getparm(): bad response to %s\n", descr);
free(resp);
return -1;
}
status -= 3;
if (status < 0) {
pmsg_error("unexpected return value %d from jtag3_command()\n", status);
free(resp);
return -1;
}
memcpy(value, resp + 3, (length < status? length: status));
free(resp);
return 0;
}
/*
* Write an emulator parameter.
*/
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
int jtag3_setparm(const PROGRAMMER *pgm, unsigned char scope,
unsigned char section, unsigned char parm,
unsigned char *value, unsigned char length) {
int status;
unsigned char *buf, *resp;
char descr[60];
pmsg_notice2("jtag3_setparm()\n");
sprintf(descr, "set parameter (scope 0x%02x, section %d, parm %d)",
scope, section, parm);
if ((buf = malloc(6 + length)) == NULL) {
pmsg_error("out of memory\n");
return -1;
}
buf[0] = scope;
buf[1] = CMD3_SET_PARAMETER;
buf[2] = 0;
buf[3] = section;
buf[4] = parm;
buf[5] = length;
memcpy(buf + 6, value, length);
status = jtag3_command(pgm, buf, length + 6, &resp, descr);
free(buf);
if (status >= 0)
free(resp);
return status;
}
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
int jtag3_read_sib(const PROGRAMMER *pgm, const AVRPART *p, char *sib) {
int status;
unsigned char cmd[12];
unsigned char *resp = NULL;
cmd[0] = SCOPE_AVR;
cmd[1] = CMD3_READ_MEMORY;
cmd[2] = 0;
cmd[3] = MTYPE_SIB;
u32_to_b4(cmd + 4, 0);
u32_to_b4(cmd + 8, AVR_SIBLEN);
if ((status = jtag3_command(pgm, cmd, 12, &resp, "read SIB")) < 0)
return status;
memcpy(sib, resp+3, AVR_SIBLEN);
sib[AVR_SIBLEN] = 0; // Zero terminate string
pmsg_debug("jtag3_read_sib(): received SIB: %s\n", sib);
free(resp);
return 0;
}
int jtag3_set_vtarget(const PROGRAMMER *pgm, double v) {
unsigned uaref, utarg;
unsigned char buf[2];
utarg = (unsigned)(v * 1000);
if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_VTARGET, buf, 2) < 0) {
pmsg_warning("cannot obtain V[target]\n");
}
uaref = b2_to_u16(buf);
u16_to_b2(buf, utarg);
pmsg_info("jtag3_set_vtarget(): changing V[target] from %.1f to %.1f\n", uaref / 1000.0, v);
if (jtag3_setparm(pgm, SCOPE_GENERAL, 1, PARM3_VADJUST, buf, sizeof(buf)) < 0) {
pmsg_error("cannot confirm new V[target] value\n");
return -1;
}
return 0;
}
void jtag3_display(const PROGRAMMER *pgm, const char *p) {
unsigned char parms[5];
unsigned char *resp = NULL;
const char *sn;
/*
* Ask for:
* PARM3_HW_VER (1 byte)
* PARM3_FW_MAJOR (1 byte)
* PARM3_FW_MINOR (1 byte)
* PARM3_FW_RELEASE (2 bytes)
*/
if (jtag3_getparm(pgm, SCOPE_GENERAL, 0, PARM3_HW_VER, parms, 5) < 0)
return;
// Use serial number pulled from the USB driver. If not present, query the programmer
if (pgm->usbsn && *pgm->usbsn)
sn = pgm->usbsn;
else {
unsigned char cmd[4], c;
int status;
cmd[0] = SCOPE_INFO;
cmd[1] = CMD3_GET_INFO;
cmd[2] = 0;
cmd[3] = CMD3_INFO_SERIAL;
if ((status = jtag3_command(pgm, cmd, 4, &resp, "get info (serial number)")) < 0) {
free(resp);
return;
}
c = resp[1];
if (c != RSP3_INFO) {
pmsg_error("response is not RSP3_INFO\n");
free(resp);
return;
}
if (status < 3) {
msg_error("unexpected response from CMD3_GET_INFO command\n");
free(resp);
return;
}
memmove(resp, resp + 3, status - 3);
resp[status - 3] = 0;
sn = (const char*)resp;
}
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("%sSerial number : %s", p, sn);
free(resp);
}
void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp) {
unsigned char prog_mode[2];
unsigned char buf[3];
if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_VTARGET, buf, 2) < 0)
return;
msg_info("%sVtarget : %.2f V\n", p, b2_to_u16(buf)/1000.0);
// Print features unique to the Power Debugger
2022-10-02 08:41:40 +00:00
for(LNODEID ln=lfirst(pgm->id); ln; ln=lnext(ln)) {
if(matches(ldata(ln), "powerdebugger")) {
short analog_raw_data;
// Read generator set voltage value (VOUT)
if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_VADJUST, buf, 2) < 0)
return;
analog_raw_data = b2_to_u16(buf);
fmsg_out(fp, "%sVout set : %.2f V\n", p, analog_raw_data / 1000.0);
2022-10-02 08:41:40 +00:00
// Read measured generator voltage value (VOUT)
if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_TSUP_VOLTAGE_MEAS, buf, 2) < 0)
return;
analog_raw_data = ((buf[0] & 0x0F) << 8) + buf[1];
if ((buf[0] & 0xF0) != 0x30)
pmsg_error("invalid PARM3_TSUP_VOLTAGE_MEAS data packet format\n");
2022-10-02 08:41:40 +00:00
else {
if (analog_raw_data & 0x0800)
analog_raw_data |= 0xF000;
fmsg_out(fp, "%sVout measured : %.02f V\n", p, (float) analog_raw_data / -200.0);
2022-10-02 08:41:40 +00:00
}
2022-10-02 08:41:40 +00:00
// Read channel A voltage
if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_ANALOG_A_VOLTAGE, buf, 2) < 0)
return;
analog_raw_data = ((buf[0] & 0x0F) << 8) + buf[1];
if ((buf[0] & 0xF0) != 0x20)
pmsg_error("invalid PARM3_ANALOG_A_VOLTAGE data packet format\n");
2022-10-02 08:41:40 +00:00
else {
if (analog_raw_data & 0x0800)
analog_raw_data |= 0xF000;
fmsg_out(fp, "%sCh A voltage : %.03f V\n", p, (float) analog_raw_data / -200.0);
2022-10-02 08:41:40 +00:00
}
2022-10-02 08:41:40 +00:00
// Read channel A current
if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_ANALOG_A_CURRENT, buf, 3) < 0)
return;
analog_raw_data = (buf[1] << 8) + buf[2];
if (buf[0] != 0x90)
pmsg_error("invalid PARM3_ANALOG_A_CURRENT data packet format\n");
2022-10-02 08:41:40 +00:00
else
fmsg_out(fp, "%sCh A current : %.3f mA\n", p, (float) analog_raw_data * 0.003472);
2022-10-02 08:41:40 +00:00
// Read channel B voltage
if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_ANALOG_B_VOLTAGE, buf, 2) < 0)
return;
analog_raw_data = ((buf[0] & 0x0F) << 8) + buf[1];
if ((buf[0] & 0xF0) != 0x10)
pmsg_error("invalid PARM3_ANALOG_B_VOLTAGE data packet format\n");
2022-10-02 08:41:40 +00:00
else {
if (analog_raw_data & 0x0800)
analog_raw_data |= 0xF000;
fmsg_out(fp, "%sCh B voltage : %.03f V\n", p, (float) analog_raw_data / -200.0);
2022-10-02 08:41:40 +00:00
}
2022-10-02 08:41:40 +00:00
// Read channel B current
if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_ANALOG_B_CURRENT, buf, 3) < 0)
return;
analog_raw_data = ((buf[0] & 0x0F) << 8) + buf[1];
if ((buf[0] & 0xF0) != 0x00)
pmsg_error("invalid PARM3_ANALOG_B_CURRENT data packet format\n");
2022-10-02 08:41:40 +00:00
else {
if (analog_raw_data & 0x0800)
analog_raw_data |= 0xF000;
fmsg_out(fp, "%sCh B current : %.3f mA\n", p, (float) analog_raw_data * 0.555556);
2022-10-02 08:41:40 +00:00
}
break;
}
}
2022-12-13 14:07:14 +00:00
// Print clocks if programmer typ is not TPI
if (strcmp(pgm->type, "JTAGICE3_TPI")) {
// Get current programming mode and target type from to determine what data to print
if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CONNECTION, prog_mode, 1) < 0)
2022-12-13 14:07:14 +00:00
return;
if (jtag3_getparm(pgm, SCOPE_AVR, 0, PARM3_ARCH, &prog_mode[1], 1) < 0)
2022-12-13 14:07:14 +00:00
return;
if (prog_mode[0] == PARM3_CONN_JTAG) {
if (prog_mode[1] == PARM3_ARCH_XMEGA) {
if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_XMEGA_JTAG, buf, 2) < 0)
return;
if (b2_to_u16(buf) > 0)
fmsg_out(fp, "%sJTAG clk Xmega : %u kHz\n", p, b2_to_u16(buf));
} else {
if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_MEGA_PROG, buf, 2) < 0)
return;
if (b2_to_u16(buf) > 0)
fmsg_out(fp, "%sJTAG clk prog. : %u kHz\n", p, b2_to_u16(buf));
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 clk debug : %u kHz\n", p, b2_to_u16(buf));
}
2022-12-13 14:07:14 +00:00
}
else if (prog_mode[0] == PARM3_CONN_PDI || prog_mode[0] == PARM3_CONN_UPDI) {
if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_XMEGA_PDI, buf, 2) < 0)
return;
if (b2_to_u16(buf) > 0)
fmsg_out(fp, "%sPDI/UPDI clk : %u kHz\n", p, b2_to_u16(buf));
2022-12-13 14:07:14 +00:00
}
}
fmsg_out(fp, "\n");
}
static void jtag3_print_parms(const PROGRAMMER *pgm, FILE *fp) {
jtag3_print_parms1(pgm, "", fp);
}
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
static unsigned char jtag3_memtype(const PROGRAMMER *pgm, const AVRPART *p, unsigned long addr) {
if (p->prog_modes & PM_PDI) {
if (addr >= PDATA(pgm)->boot_start)
return MTYPE_BOOT_FLASH;
else
return MTYPE_FLASH;
} else {
return MTYPE_FLASH_PAGE;
}
}
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
static unsigned int jtag3_memaddr(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m, unsigned long addr) {
if (p->prog_modes & PM_PDI) {
if (addr >= PDATA(pgm)->boot_start)
/*
* all memories but "flash" are smaller than boot_start anyway, so
* no need for an extra check we are operating on "flash"
*/
return addr - PDATA(pgm)->boot_start;
else
/* normal flash, or anything else */
return addr;
}
// Non-Xmega device
if (p->prog_modes & PM_UPDI) {
if (strcmp(m->desc, "flash") == 0) {
return addr;
}
else if (m->size == 1) {
addr = m->offset;
}
else if (m->size > 1) {
addr += m->offset;
}
}
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;
2022-11-29 19:34:05 +00:00
} 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) {
2022-11-29 19:34:05 +00:00
pmsg_error("jtag3_send_tpi(): out of memory for command packet\n");
exit(1);
}
cmdbuf[0] = SCOPE_AVR_TPI;
if (len > INT_MAX) {
pmsg_error("invalid jtag3_send_tpi() packet length %zu\n", len);
free(cmdbuf);
return -1;
}
memcpy(cmdbuf + 1, data, len);
2022-11-29 19:34:05 +00:00
msg_trace("[TPI send] ");
for (size_t i=1; i<=len; i++)
msg_trace("0x%02x ", cmdbuf[i]);
2022-11-29 19:34:05 +00:00
msg_trace("\n");
rv = jtag3_send(pgm, cmdbuf, len + 1);
free(cmdbuf);
return rv;
}
2022-11-29 19:34:05 +00:00
int jtag3_recv_tpi(const PROGRAMMER *pgm, unsigned char **msg) {
int rv;
2022-11-29 19:34:05 +00:00
rv = jtag3_recv(pgm, msg);
if (rv <= 0) {
2022-11-29 19:34:05 +00:00
pmsg_error("jtag3_recv_tpi(): unable to receive\n");
return -1;
}
rv = rv - 1;
2022-11-29 19:34:05 +00:00
memcpy(*msg, *msg + 1, rv);
2022-11-29 19:34:05 +00:00
msg_trace("[TPI recv] ");
for (int i=0; i<rv; i++)
2022-11-29 19:34:05 +00:00
msg_trace("0x%02x ", (*msg)[i]);
msg_trace("\n");
2022-11-29 19:34:05 +00:00
return rv;
}
2022-11-29 19:34:05 +00:00
int jtag3_command_tpi(const PROGRAMMER *pgm, unsigned char *cmd, unsigned int cmdlen,
unsigned char **resp, const char *descr) {
int status;
unsigned char c;
jtag3_send_tpi(pgm, cmd, cmdlen);
status = jtag3_recv_tpi(pgm, resp);
if (status <= 0) {
msg_notice2("\n");
pmsg_notice2("TPI %s command: timeout/error communicating with programmer (status %d)\n", descr, status);
return LIBAVRDUDE_GENERAL_FAILURE;
}
c = (*resp)[1];
if (c != XPRG_ERR_OK) {
2022-11-30 22:07:05 +00:00
pmsg_error("[TPI] command %s FAILED! Status: 0x%02x\n", descr, c);
2022-11-29 19:34:05 +00:00
status = (*resp)[3];
free(*resp);
resp = 0;
return LIBAVRDUDE_GENERAL_FAILURE;
}
return status;
}
2022-11-30 22:07:05 +00:00
/*
* initialize the AVR device and prepare it to accept commands
*/
static int jtag3_initialize_tpi(const PROGRAMMER *pgm, const AVRPART *p) {
unsigned char cmd[3];
2022-11-30 22:07:05 +00:00
unsigned char* resp;
int status;
pmsg_notice2("jtag3_initialize_tpi() start\n");
2022-11-30 22:07:05 +00:00
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);
2022-12-12 13:20:16 +00:00
jtag3_print_parms1(pgm, progbuf, stderr);
2022-12-12 13:20:16 +00:00
2022-11-30 22:07:05 +00:00
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) {
2022-11-30 22:07:05 +00:00
unsigned char cmd[1];
2022-11-29 19:34:05 +00:00
unsigned char* resp;
2022-11-30 22:07:05 +00:00
int status;
2022-11-30 22:07:05 +00:00
cmd[0] = XPRG_CMD_LEAVE_PROGMODE;
2022-11-30 22:07:05 +00:00
if ((status = jtag3_command_tpi(pgm, cmd, 1, &resp, "Leave Progmode")) < 0)
return;
2022-11-29 19:34:05 +00:00
free(resp);
}
static int jtag3_read_byte_tpi(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
unsigned long addr, unsigned char * value) {
2022-11-30 22:07:05 +00:00
int status;
2022-11-29 23:14:19 +00:00
const size_t len = 8;
2022-11-30 22:07:05 +00:00
unsigned char cmd[8]; // Using "len" as array length causes msvc build jobs to fail with error C2057: expected constant expression
2022-11-29 19:34:05 +00:00
unsigned char* resp;
unsigned long paddr = 0UL;
2022-11-30 22:07:05 +00:00
msg_notice2("\n");
pmsg_notice2("jtag3_read_byte_tpi(.., %s, 0x%lx, ...)\n", mem->desc, addr);
paddr = mem->offset + addr;
2022-11-30 22:07:05 +00:00
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
2022-11-30 23:01:29 +00:00
if ((status = jtag3_command_tpi(pgm, cmd, len, &resp, "Read Byte")) < 0)
return -1;
2022-11-29 19:34:05 +00:00
*value = resp[2];
free(resp);
return 0;
}
static int jtag3_erase_tpi(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
2022-11-29 19:34:05 +00:00
unsigned long addr) {
2022-11-29 23:14:19 +00:00
const size_t len = 6;
2022-11-30 22:07:05 +00:00
unsigned char cmd[6]; // Using "len" as array length causes msvc build jobs to fail with error C2057: expected constant expression
2022-11-29 19:34:05 +00:00
unsigned char* resp;
2022-11-30 22:07:05 +00:00
int status;
unsigned long paddr = 0UL;
2022-11-30 22:07:05 +00:00
cmd[0] = XPRG_CMD_ERASE;
if (strcmp(mem->desc, "fuse") == 0) {
2022-11-30 22:07:05 +00:00
cmd[1] = XPRG_ERASE_CONFIG;
} else if (strcmp(mem->desc, "flash") == 0) {
2022-11-30 22:07:05 +00:00
cmd[1] = XPRG_ERASE_APP;
} else {
pmsg_error("jtag3_erase_tpi() unsupported memory: %s\n", mem->desc);
return -1;
}
2022-11-29 19:34:05 +00:00
paddr = (mem->offset + addr) | 0x01; // An erase is triggered by an access to the hi-byte
2022-11-30 22:07:05 +00:00
u32_to_b4_big_endian((cmd+2), paddr);
2022-11-30 23:01:29 +00:00
if ((status = jtag3_command_tpi(pgm, cmd, len, &resp, "Erase")) < 0)
return -1;
2022-11-29 19:34:05 +00:00
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) {
2022-11-30 22:07:05 +00:00
size_t len = 11;
size_t data_size = 2;
2022-11-30 22:07:05 +00:00
unsigned char cmd[17];
2022-11-29 19:34:05 +00:00
unsigned char* resp;
2022-11-30 22:07:05 +00:00
int status;
unsigned long paddr = 0UL;
2022-11-30 22:07:05 +00:00
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;
}
}
2022-11-30 22:07:05 +00:00
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
2022-11-30 22:07:05 +00:00
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
2022-11-30 23:01:29 +00:00
if ((status = jtag3_command_tpi(pgm, cmd, len, &resp, "Write Byte")) < 0)
return -1;
2022-11-29 19:34:05 +00:00
free(resp);
return 0;
}
static int jtag3_chip_erase_tpi(const PROGRAMMER *pgm, const AVRPART *p) {
2022-11-29 23:14:19 +00:00
const size_t len = 6;
2022-11-30 22:07:05 +00:00
unsigned char cmd[6]; // Using "len" as array length causes msvc build jobs to fail with error C2057: expected constant expression
2022-11-29 19:34:05 +00:00
unsigned char* resp;
2022-11-30 22:07:05 +00:00
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
2022-11-30 22:07:05 +00:00
paddr = m->offset | 0x01;
2022-11-30 22:07:05 +00:00
cmd[0] = XPRG_CMD_ERASE;
cmd[1] = XPRG_ERASE_CHIP;
u32_to_b4_big_endian((cmd+2), paddr);
2022-11-30 23:01:29 +00:00
if ((status = jtag3_command_tpi(pgm, cmd, len, &resp, "Chip Erase")) < 0)
return -1;
2022-11-29 19:34:05 +00:00
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");
}
2022-11-29 19:34:05 +00:00
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;
2022-11-29 23:14:19 +00:00
msg_notice2("\n");
2022-11-29 19:34:05 +00:00
pmsg_notice2("jtag3_paged_load_tpi(.., %s, %d, 0x%04x, %d)\n",
m->desc, page_size, addr, n_bytes);
if(m->offset)
2022-11-30 23:01:29 +00:00
imsg_notice2("mapped to address: 0x%04x\n", (addr+m->offset));
2022-11-29 19:34:05 +00:00
cmd[0] = XPRG_CMD_READ_MEM;
cmd[1] = tpi_get_memtype(m);
if(m->blocksize > (int) page_size)
2022-11-29 19:34:05 +00:00
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
2022-11-30 23:01:29 +00:00
if ((status = jtag3_command_tpi(pgm, cmd, 8, &resp, "Read Memory")) < 0)
2022-11-29 19:34:05 +00:00
return -1;
if (resp[1] != XPRG_ERR_OK || status < (int) block_size + 2) {
2022-11-29 19:34:05 +00:00
pmsg_error("wrong/short reply to read memory command\n");
serial_recv_timeout = otimeout;
free(resp);
return -1;
}
if (status < 2) {
pmsg_error("unexpected return value %d from jtag3_paged_load_tpi()\n", status);
free(resp);
return -1;
}
2022-11-29 19:34:05 +00:00
memcpy(m->buf + addr, resp + 2, status - 2);
free(resp);
}
serial_recv_timeout = otimeout;
return n_bytes;
}
2022-11-29 23:14:19 +00:00
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)
2022-11-30 23:01:29 +00:00
imsg_notice2("mapped to address: 0x%04x\n", (addr+m->offset));
2022-11-29 23:14:19 +00:00
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,
2022-11-30 23:01:29 +00:00
&resp, "Write Memory")) < 0) {
2022-11-29 23:14:19 +00:00
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";
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
void jtag3_initpgm(PROGRAMMER *pgm) {
strcpy(pgm->type, "JTAGICE3");
/*
* mandatory functions
*/
pgm->initialize = jtag3_initialize;
pgm->display = jtag3_display;
pgm->enable = jtag3_enable;
pgm->disable = jtag3_disable;
pgm->program_enable = jtag3_program_enable_dummy;
pgm->chip_erase = jtag3_chip_erase;
pgm->open = jtag3_open;
pgm->close = jtag3_close;
pgm->read_byte = jtag3_read_byte;
pgm->write_byte = jtag3_write_byte;
/*
* optional functions
*/
pgm->paged_write = jtag3_paged_write;
pgm->paged_load = jtag3_paged_load;
pgm->page_erase = jtag3_page_erase;
pgm->print_parms = jtag3_print_parms;
pgm->set_sck_period = jtag3_set_sck_period;
pgm->parseextparams = jtag3_parseextparms;
pgm->setup = jtag3_setup;
pgm->teardown = jtag3_teardown;
pgm->page_size = 256;
pgm->flag = PGM_FL_IS_JTAG;
2022-10-02 08:41:40 +00:00
for(LNODEID ln=lfirst(pgm->id); ln; ln=lnext(ln)) {
if (matches(ldata(ln), "powerdebugger")) {
pgm->set_vtarget = jtag3_set_vtarget;
break;
}
}
}
const char jtag3_dw_desc[] = "Atmel JTAGICE3 in debugWire mode";
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
void jtag3_dw_initpgm(PROGRAMMER *pgm) {
strcpy(pgm->type, "JTAGICE3_DW");
/*
* mandatory functions
*/
pgm->initialize = jtag3_initialize;
pgm->display = jtag3_display;
pgm->enable = jtag3_enable;
pgm->disable = jtag3_disable;
pgm->program_enable = jtag3_program_enable_dummy;
pgm->chip_erase = jtag3_chip_erase_dw;
pgm->open = jtag3_open_dw;
pgm->close = jtag3_close;
pgm->read_byte = jtag3_read_byte;
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_DW;
2022-10-02 08:41:40 +00:00
for(LNODEID ln=lfirst(pgm->id); ln; ln=lnext(ln)) {
if (matches(ldata(ln), "powerdebugger")) {
pgm->set_vtarget = jtag3_set_vtarget;
break;
}
}
}
const char jtag3_pdi_desc[] = "Atmel JTAGICE3 in PDI mode";
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
void jtag3_pdi_initpgm(PROGRAMMER *pgm) {
strcpy(pgm->type, "JTAGICE3_PDI");
/*
* mandatory functions
*/
pgm->initialize = jtag3_initialize;
pgm->display = jtag3_display;
pgm->enable = jtag3_enable;
pgm->disable = jtag3_disable;
pgm->program_enable = jtag3_program_enable_dummy;
pgm->chip_erase = jtag3_chip_erase;
pgm->open = jtag3_open_pdi;
pgm->close = jtag3_close;
pgm->read_byte = jtag3_read_byte;
pgm->write_byte = jtag3_write_byte;
/*
* optional functions
*/
pgm->paged_write = jtag3_paged_write;
pgm->paged_load = jtag3_paged_load;
pgm->page_erase = jtag3_page_erase;
pgm->print_parms = jtag3_print_parms;
pgm->set_sck_period = jtag3_set_sck_period;
pgm->setup = jtag3_setup;
pgm->teardown = jtag3_teardown;
pgm->page_size = 256;
pgm->flag = PGM_FL_IS_PDI;
2022-10-02 08:41:40 +00:00
for(LNODEID ln=lfirst(pgm->id); ln; ln=lnext(ln)) {
if (matches(ldata(ln), "powerdebugger")) {
pgm->set_vtarget = jtag3_set_vtarget;
break;
}
}
}
const char jtag3_updi_desc[] = "Atmel JTAGICE3 in UPDI mode";
Use const in PROGRAMMER function arguments where appropriate In order to get meaningful const properties for the PROGRAMMER, AVRPART and AVRMEM arguments, some code needed to be moved around, otherwise a network of "tainted" assignments risked rendering nothing const: - Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm, const AVRPART *p); this allows changes in the PROGRAMMER structure after the part is known. For example, use TPI, UPDI, PDI functions in that programmer appropriate to the part. This used to be done later in the process, eg, in the initialize() function, which "taints" all other programmer functions wrt const and sometimes requires other finessing with flags etc. Much clearer with the modified enable() interface. - Move TPI initpgm-type code from initialize() to enable() --- note that initpgm() does not have the info at the time when it is called whether or not TPI is required - buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate modification of the flag does not change PROGRAMMER structure) - Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and FLAGS32_WRITE bits - Move the xbeeResetPin component to private data in stk500.c as this is needed by xbee when it saddles on the stk500 code (previously, the flags component of the part was re-dedicated to this) - Change the way the "chained" private data are used in jtag3.c whilst keeping the PROGRAMMER structure read-only otherwise - In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to stk500v2_enable() so the former keeps the PROGRAMMER structure read-only (for const assertion). - In usbasp change the code from changing PROGRAMMER functions late to dispatching to TPI or regular SPI protocol functions at runtime; reason being the decision whether to use TPI protocol is done at run-time depending on the capability of the attached programmer Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
void jtag3_updi_initpgm(PROGRAMMER *pgm) {
strcpy(pgm->type, "JTAGICE3_UPDI");
/*
* mandatory functions
*/
pgm->initialize = jtag3_initialize;
pgm->parseextparams = jtag3_parseextparms;
pgm->display = jtag3_display;
pgm->enable = jtag3_enable;
pgm->disable = jtag3_disable;
pgm->program_enable = jtag3_program_enable_dummy;
pgm->chip_erase = jtag3_chip_erase;
pgm->open = jtag3_open_updi;
pgm->close = jtag3_close;
pgm->read_byte = jtag3_read_byte;
pgm->write_byte = jtag3_write_byte;
/*
* optional functions
*/
pgm->paged_write = jtag3_paged_write;
pgm->paged_load = jtag3_paged_load;
pgm->page_erase = jtag3_page_erase;
pgm->print_parms = jtag3_print_parms;
pgm->set_sck_period = jtag3_set_sck_period;
pgm->setup = jtag3_setup;
pgm->teardown = jtag3_teardown;
pgm->page_size = 256;
pgm->flag = PGM_FL_IS_UPDI;
pgm->unlock = jtag3_unlock_erase_key;
pgm->read_sib = jtag3_read_sib;
2022-10-02 08:41:40 +00:00
for(LNODEID ln=lfirst(pgm->id); ln; ln=lnext(ln)) {
if (matches(ldata(ln), "powerdebugger") ||
matches(ldata(ln), "pkob")) {
pgm->set_vtarget = jtag3_set_vtarget;
break;
}
}
}
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
*/
2022-11-29 23:14:19 +00:00
pgm->paged_write = jtag3_paged_write_tpi;
2022-11-29 19:34:05 +00:00
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;
}