2001-01-19 02:46:50 +00:00
|
|
|
/*
|
2003-02-08 04:17:25 +00:00
|
|
|
* avrdude - A Downloader/Uploader for AVR device programmers
|
2004-12-22 01:52:45 +00:00
|
|
|
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bsdhome.com>
|
2001-01-19 02:46:50 +00:00
|
|
|
*
|
2003-02-06 19:08:33 +00:00
|
|
|
* 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.
|
2001-01-19 02:46:50 +00:00
|
|
|
*
|
2003-02-06 19:08:33 +00:00
|
|
|
* 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.
|
2001-01-19 02:46:50 +00:00
|
|
|
*
|
2003-02-06 19:08:33 +00:00
|
|
|
* You should have received a copy of the GNU General Public License
|
2012-11-20 14:03:50 +00:00
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2001-01-19 02:46:50 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* $Id$ */
|
|
|
|
|
2003-02-14 20:34:03 +00:00
|
|
|
#include "ac_cfg.h"
|
2001-01-19 02:46:50 +00:00
|
|
|
|
2022-08-10 15:24:26 +00:00
|
|
|
#include <ctype.h>
|
2003-11-22 03:25:48 +00:00
|
|
|
#include <string.h>
|
2001-01-19 02:46:50 +00:00
|
|
|
#include <stdio.h>
|
2022-10-08 17:02:03 +00:00
|
|
|
#include <stddef.h>
|
2022-02-20 18:08:30 +00:00
|
|
|
#include <stdint.h>
|
2001-01-19 02:46:50 +00:00
|
|
|
#include <stdlib.h>
|
2022-10-11 13:40:37 +00:00
|
|
|
#include <stddef.h>
|
2022-07-13 10:48:29 +00:00
|
|
|
#include <stdarg.h>
|
2001-01-19 02:46:50 +00:00
|
|
|
#include <limits.h>
|
2022-07-13 10:38:43 +00:00
|
|
|
#include <unistd.h>
|
2022-07-12 10:19:47 +00:00
|
|
|
#include <errno.h>
|
2003-02-27 20:08:54 +00:00
|
|
|
|
|
|
|
#if defined(HAVE_LIBREADLINE)
|
|
|
|
# include <readline/readline.h>
|
|
|
|
# include <readline/history.h>
|
|
|
|
#endif
|
2001-01-19 02:46:50 +00:00
|
|
|
|
2007-01-24 21:07:54 +00:00
|
|
|
#include "avrdude.h"
|
2014-05-19 10:01:59 +00:00
|
|
|
#include "term.h"
|
2001-01-19 02:46:50 +00:00
|
|
|
|
|
|
|
struct command {
|
2022-10-11 13:40:37 +00:00
|
|
|
char *name;
|
|
|
|
int (*func)(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
|
|
|
size_t fnoff;
|
|
|
|
char *desc;
|
2001-01-19 02:46:50 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2022-10-11 13:40:37 +00:00
|
|
|
static int cmd_dump (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
|
|
|
static int cmd_write (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
|
|
|
static int cmd_flush (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
|
|
|
static int cmd_abort (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
|
|
|
static int cmd_erase (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
|
|
|
static int cmd_pgerase(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
|
|
|
static int cmd_sig (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
|
|
|
static int cmd_part (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
|
|
|
static int cmd_help (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
|
|
|
static int cmd_quit (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
|
|
|
static int cmd_send (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
|
|
|
static int cmd_parms (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
|
|
|
static int cmd_vtarg (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
|
|
|
static int cmd_varef (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
|
|
|
static int cmd_fosc (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
|
|
|
static int cmd_sck (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
|
|
|
static int cmd_spi (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
|
|
|
static int cmd_pgm (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
|
|
|
static int cmd_verbose(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
|
|
|
static int cmd_quell (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
|
|
|
|
|
|
|
#define _fo(x) offsetof(PROGRAMMER, x)
|
2022-07-12 12:11:10 +00:00
|
|
|
|
2001-01-19 02:46:50 +00:00
|
|
|
struct command cmd[] = {
|
2022-10-11 13:40:37 +00:00
|
|
|
{ "dump", cmd_dump, _fo(read_byte_cached), "%s <memory> [<addr> <len> | <addr> ... | <addr> | ...]" },
|
|
|
|
{ "read", cmd_dump, _fo(read_byte_cached), "alias for dump" },
|
|
|
|
{ "write", cmd_write, _fo(write_byte_cached), "write <memory> <addr> <data>[,] {<data>[,]}" },
|
|
|
|
{ "", cmd_write, _fo(write_byte_cached), "write <memory> <addr> <len> <data>[,] {<data>[,]} ..." },
|
|
|
|
{ "flush", cmd_flush, _fo(flush_cache), "synchronise flash & EEPROM writes with the device" },
|
|
|
|
{ "abort", cmd_abort, _fo(reset_cache), "abort flash & EEPROM writes (reset the r/w cache)" },
|
|
|
|
{ "erase", cmd_erase, _fo(chip_erase_cached), "perform a chip erase" },
|
|
|
|
{ "pgerase", cmd_pgerase, _fo(page_erase), "pgerase <memory> <addr>" },
|
|
|
|
{ "sig", cmd_sig, _fo(open), "display device signature bytes" },
|
|
|
|
{ "part", cmd_part, _fo(open), "display the current part information" },
|
|
|
|
{ "send", cmd_send, _fo(cmd), "send a raw command: %s <b1> <b2> <b3> <b4>" },
|
|
|
|
{ "parms", cmd_parms, _fo(print_parms), "display adjustable parameters" },
|
|
|
|
{ "vtarg", cmd_vtarg, _fo(set_vtarget), "set <V[target]>" },
|
|
|
|
{ "varef", cmd_varef, _fo(set_varef), "set <V[aref]>" },
|
|
|
|
{ "fosc", cmd_fosc, _fo(set_fosc), "set <oscillator frequency>" },
|
|
|
|
{ "sck", cmd_sck, _fo(set_sck_period), "set <SCK period>" },
|
|
|
|
{ "spi", cmd_spi, _fo(setpin), "enter direct SPI mode" },
|
|
|
|
{ "pgm", cmd_pgm, _fo(setpin), "return to programming mode" },
|
|
|
|
{ "verbose", cmd_verbose, _fo(open), "change verbosity" },
|
|
|
|
{ "quell", cmd_quell, _fo(open), "set quell level for progress bars" },
|
|
|
|
{ "help", cmd_help, _fo(open), "show help message" },
|
|
|
|
{ "?", cmd_help, _fo(open), "same as help" },
|
|
|
|
{ "quit", cmd_quit, _fo(open), "quit after writing out cache for flash & EEPROM" }
|
2001-01-19 02:46:50 +00:00
|
|
|
};
|
|
|
|
|
2022-07-12 10:59:42 +00:00
|
|
|
#define NCMDS ((int)(sizeof(cmd)/sizeof(struct command)))
|
2001-01-19 02:46:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2009-02-17 15:31:27 +00:00
|
|
|
static int spi_mode = 0;
|
2001-01-19 02:46:50 +00:00
|
|
|
|
2022-10-11 13:40:37 +00:00
|
|
|
static int nexttok(char *buf, char **tok, char **next) {
|
2022-07-13 10:19:21 +00:00
|
|
|
unsigned char *q, *n;
|
2001-01-19 02:46:50 +00:00
|
|
|
|
2022-07-13 10:19:21 +00:00
|
|
|
q = (unsigned char *) buf;
|
|
|
|
while (isspace(*q))
|
2001-01-19 02:46:50 +00:00
|
|
|
q++;
|
2010-01-22 16:40:17 +00:00
|
|
|
|
2001-01-19 02:46:50 +00:00
|
|
|
/* isolate first token */
|
2022-04-01 14:52:59 +00:00
|
|
|
n = q;
|
|
|
|
uint8_t quotes = 0;
|
2022-07-13 10:19:21 +00:00
|
|
|
while (*n && (!isspace(*n) || quotes)) {
|
2022-07-15 17:50:20 +00:00
|
|
|
// poor man's quote and escape processing
|
|
|
|
if (*n == '"' || *n == '\'')
|
2022-04-01 14:52:59 +00:00
|
|
|
quotes++;
|
2022-07-15 17:50:20 +00:00
|
|
|
else if(*n == '\\' && n[1])
|
|
|
|
n++;
|
|
|
|
else if (isspace(*n) && (n > q+1) && (n[-1] == '"' || n[-1] == '\''))
|
2022-04-01 14:52:59 +00:00
|
|
|
break;
|
2001-01-19 02:46:50 +00:00
|
|
|
n++;
|
2022-04-01 14:52:59 +00:00
|
|
|
}
|
2001-01-19 02:46:50 +00:00
|
|
|
|
|
|
|
if (*n) {
|
|
|
|
*n = 0;
|
|
|
|
n++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* find start of next token */
|
2022-07-13 10:19:21 +00:00
|
|
|
while (isspace(*n))
|
2001-01-19 02:46:50 +00:00
|
|
|
n++;
|
|
|
|
|
2022-07-13 10:19:21 +00:00
|
|
|
*tok = (char *) q;
|
|
|
|
*next = (char *) n;
|
2001-01-19 02:46:50 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-10-11 13:40:37 +00:00
|
|
|
static int hexdump_line(char *buffer, unsigned char *p, int n, int pad) {
|
|
|
|
char *hexdata = "0123456789abcdef";
|
|
|
|
char *b = buffer;
|
2022-07-12 10:59:42 +00:00
|
|
|
int i = 0;
|
|
|
|
int j = 0;
|
2001-01-19 02:46:50 +00:00
|
|
|
|
|
|
|
for (i=0; i<n; i++) {
|
|
|
|
if (i && ((i % 8) == 0))
|
|
|
|
b[j++] = ' ';
|
|
|
|
b[j++] = hexdata[(p[i] & 0xf0) >> 4];
|
|
|
|
b[j++] = hexdata[(p[i] & 0x0f)];
|
|
|
|
if (i < 15)
|
|
|
|
b[j++] = ' ';
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i=j; i<pad; i++)
|
|
|
|
b[i] = ' ';
|
|
|
|
|
|
|
|
b[i] = 0;
|
|
|
|
|
|
|
|
for (i=0; i<pad; i++) {
|
|
|
|
if (!((b[i] == '0') || (b[i] == ' ')))
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-10-11 13:40:37 +00:00
|
|
|
static int chardump_line(char *buffer, unsigned char *p, int n, int pad) {
|
2001-01-19 02:46:50 +00:00
|
|
|
int i;
|
2022-07-13 10:19:21 +00:00
|
|
|
unsigned char b[128];
|
2001-01-19 02:46:50 +00:00
|
|
|
|
2022-07-13 10:19:21 +00:00
|
|
|
// sanity check
|
|
|
|
n = n < 1? 1: n > sizeof b? sizeof b: n;
|
|
|
|
|
|
|
|
memcpy(b, p, n);
|
2022-07-14 16:16:30 +00:00
|
|
|
for (int i = 0; i < n; i++)
|
|
|
|
buffer[i] = isascii(b[i]) && isspace(b[i])? ' ':
|
|
|
|
isascii(b[i]) && isgraph(b[i])? b[i]: '.';
|
2001-01-19 02:46:50 +00:00
|
|
|
|
2022-02-28 21:40:17 +00:00
|
|
|
for (i = n; i < pad; i++)
|
2001-01-19 02:46:50 +00:00
|
|
|
buffer[i] = ' ';
|
|
|
|
|
|
|
|
buffer[i] = 0;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-10-11 13:40:37 +00:00
|
|
|
static int hexdump_buf(FILE *f, int startaddr, unsigned char *buf, int len) {
|
2001-01-19 02:46:50 +00:00
|
|
|
char dst1[80];
|
|
|
|
char dst2[80];
|
|
|
|
|
2022-07-12 10:59:42 +00:00
|
|
|
int addr = startaddr;
|
2022-10-11 13:40:37 +00:00
|
|
|
unsigned char *p = (unsigned char *)buf;
|
2001-01-19 02:46:50 +00:00
|
|
|
while (len) {
|
2022-07-12 10:59:42 +00:00
|
|
|
int n = 16;
|
2001-01-19 02:46:50 +00:00
|
|
|
if (n > len)
|
|
|
|
n = len;
|
|
|
|
hexdump_line(dst1, p, n, 48);
|
|
|
|
chardump_line(dst2, p, n, 16);
|
|
|
|
fprintf(stdout, "%04x %s |%s|\n", addr, dst1, dst2);
|
|
|
|
len -= n;
|
|
|
|
addr += n;
|
|
|
|
p += n;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-10-11 13:40:37 +00:00
|
|
|
static int cmd_dump(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
2022-07-12 10:47:33 +00:00
|
|
|
if (argc < 2 || argc > 4) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO,
|
2022-07-12 10:47:33 +00:00
|
|
|
"Usage: %s <memory> <addr> <len>\n"
|
|
|
|
" %s <memory> <addr> ...\n"
|
|
|
|
" %s <memory> <addr>\n"
|
|
|
|
" %s <memory> ...\n"
|
|
|
|
" %s <memory>\n",
|
|
|
|
argv[0], argv[0], argv[0], argv[0], argv[0]);
|
|
|
|
return -1;
|
2001-01-19 02:46:50 +00:00
|
|
|
}
|
|
|
|
|
2022-02-28 21:40:17 +00:00
|
|
|
enum { read_size = 256 };
|
2022-08-15 13:25:58 +00:00
|
|
|
static const char *prevmem = "";
|
2022-10-11 13:40:37 +00:00
|
|
|
char *memtype = argv[1];
|
|
|
|
AVRMEM *mem = avr_locate_mem(p, memtype);
|
2001-11-21 02:46:55 +00:00
|
|
|
if (mem == NULL) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%s (dump): %s memory type not defined for part %s\n",
|
2022-07-12 10:58:51 +00:00
|
|
|
progname, memtype, p->desc);
|
2001-11-21 02:46:55 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2022-07-12 10:59:42 +00:00
|
|
|
int maxsize = mem->size;
|
2001-11-21 02:46:55 +00:00
|
|
|
|
2022-02-28 21:40:17 +00:00
|
|
|
// Get start address if present
|
2022-10-11 13:40:37 +00:00
|
|
|
char *end_ptr;
|
2022-07-12 10:59:42 +00:00
|
|
|
static int addr = 0;
|
2022-07-12 10:43:45 +00:00
|
|
|
|
|
|
|
if (argc >= 3 && strcmp(argv[2], "...") != 0) {
|
2022-02-28 21:40:17 +00:00
|
|
|
addr = strtoul(argv[2], &end_ptr, 0);
|
|
|
|
if (*end_ptr || (end_ptr == argv[2])) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%s (dump): can't parse address %s\n",
|
2022-07-12 10:58:51 +00:00
|
|
|
progname, argv[2]);
|
2001-01-19 03:10:53 +00:00
|
|
|
return -1;
|
2022-10-11 13:40:37 +00:00
|
|
|
} else if (addr < 0 || addr >= maxsize) {
|
|
|
|
terminal_message(MSG_INFO, "%s (dump): %s address 0x%05x is out of range [0, 0x%05x]\n",
|
|
|
|
progname, mem->desc, addr, maxsize-1);
|
2001-11-21 02:46:55 +00:00
|
|
|
return -1;
|
2001-01-19 03:10:53 +00:00
|
|
|
}
|
2001-01-19 02:46:50 +00:00
|
|
|
}
|
|
|
|
|
2022-02-28 21:40:17 +00:00
|
|
|
// Get no. bytes to read if present
|
2022-07-12 10:59:42 +00:00
|
|
|
static int len = read_size;
|
2022-02-28 21:40:17 +00:00
|
|
|
if (argc >= 3) {
|
2022-08-15 13:25:58 +00:00
|
|
|
prevmem = cache_string("");
|
2022-02-28 21:40:17 +00:00
|
|
|
if (strcmp(argv[argc - 1], "...") == 0) {
|
|
|
|
if (argc == 3)
|
|
|
|
addr = 0;
|
|
|
|
len = maxsize - addr;
|
|
|
|
} else if (argc == 4) {
|
|
|
|
len = strtol(argv[3], &end_ptr, 0);
|
|
|
|
if (*end_ptr || (end_ptr == argv[3])) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%s (dump): can't parse length %s\n",
|
2022-07-12 10:58:51 +00:00
|
|
|
progname, argv[3]);
|
2022-02-28 21:40:17 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
len = read_size;
|
2002-11-23 00:52:15 +00:00
|
|
|
}
|
2022-02-28 21:40:17 +00:00
|
|
|
}
|
|
|
|
// No address or length specified
|
|
|
|
else if (argc == 2) {
|
|
|
|
if (strncmp(prevmem, memtype, strlen(memtype)) != 0) {
|
|
|
|
addr = 0;
|
|
|
|
len = read_size;
|
2022-08-15 13:25:58 +00:00
|
|
|
prevmem = cache_string(mem->desc);
|
2002-11-23 00:52:15 +00:00
|
|
|
}
|
2022-02-28 21:40:17 +00:00
|
|
|
if (addr >= maxsize)
|
|
|
|
addr = 0; // Wrap around
|
2001-01-19 02:46:50 +00:00
|
|
|
}
|
|
|
|
|
2022-02-28 21:40:17 +00:00
|
|
|
// Trim len if nessary to not read past the end of memory
|
2001-01-19 03:10:53 +00:00
|
|
|
if ((addr + len) > maxsize)
|
|
|
|
len = maxsize - addr;
|
2001-01-19 02:46:50 +00:00
|
|
|
|
2022-10-11 13:40:37 +00:00
|
|
|
uint8_t *buf = malloc(len);
|
2001-01-19 02:46:50 +00:00
|
|
|
if (buf == NULL) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%s (dump): out of memory\n", progname);
|
2001-01-19 02:46:50 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2022-03-31 20:21:49 +00:00
|
|
|
report_progress(0, 1, "Reading");
|
2022-07-12 10:59:42 +00:00
|
|
|
for (int i = 0; i < len; i++) {
|
Provide cached byte-wise read/write API (#1106)
* Provide cached byte-wise read/write API
int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char *value);
int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char data);
int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p);
int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p);
int avr_reset_cache(const PROGRAMMER *pgm, const AVRPART *p);
avr_read_byte_cached() and avr_write_byte_cached() use a cache if paged
routines are available and if the device memory is EEPROM or flash,
otherwise they fall back to pgm->read_byte() and pgm->write_byte(),
respectively. Byte-wise cached read always gets its data from the cache,
possibly after reading a page from the device memory. Byte-wise cached
write with an address in memory range only ever modifies the cache. Any
modifications are written to the device after calling avr_flush_cache() or
when attempting to read or write from a location outside the address range
of the device memory.
avr_flush_cache() synchronises pending writes to EEPROM and flash with the
device. With some programmer and part combinations, flash (and sometimes
EEPROM, too) looks like a NOR memory, ie, one can only write 0 bits, not 1
bits. When this is detected, either page erase is deployed (eg, with parts
that have PDI/UPDI interfaces), or if that is not available, both EEPROM
and flash caches are fully read in, a pgm->chip_erase() command is issued
and both EEPROM and flash are written back to the device. Hence, it can
take minutes to ensure that a single previously cleared bit is set and,
therefore, this routine should be called sparingly.
avr_chip_erase_cached() erases the chip and discards pending writes() to
flash or EEPROM. It presets the flash cache to all 0xff alleviating the
need to read from the device flash. However, if the programmer serves
bootloaders (pgm->prog_modes & PM_SPM) then the flash cache is reset
instead, necessitating flash memory be fetched from the device on first
read; the reason for this is that bootloaders emulate chip erase and they
won't overwrite themselves (some bootloaders, eg, optiboot ignore chip
erase commands altogether) making it truly unknowable what the flash
contents on device is after a chip erase.
For EEPROM avr_chip_erase_cached() concludes that it has been deleted if a
previously cached EEPROM page that contained cleared bits now no longer
has these clear bits on the device. Only with this evidence is the EEPROM
cache preset to all 0xff otherwise the cache discards all pending writes
to EEPROM and is left unchanged otherwise.
Finally, avr_reset_cache() resets the cache without synchronising pending
writes() to the device.
2022-10-05 21:16:15 +00:00
|
|
|
int rc = pgm->read_byte_cached(pgm, p, mem, addr + i, &buf[i]);
|
2001-11-21 02:46:55 +00:00
|
|
|
if (rc != 0) {
|
Provide cached byte-wise read/write API (#1106)
* Provide cached byte-wise read/write API
int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char *value);
int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char data);
int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p);
int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p);
int avr_reset_cache(const PROGRAMMER *pgm, const AVRPART *p);
avr_read_byte_cached() and avr_write_byte_cached() use a cache if paged
routines are available and if the device memory is EEPROM or flash,
otherwise they fall back to pgm->read_byte() and pgm->write_byte(),
respectively. Byte-wise cached read always gets its data from the cache,
possibly after reading a page from the device memory. Byte-wise cached
write with an address in memory range only ever modifies the cache. Any
modifications are written to the device after calling avr_flush_cache() or
when attempting to read or write from a location outside the address range
of the device memory.
avr_flush_cache() synchronises pending writes to EEPROM and flash with the
device. With some programmer and part combinations, flash (and sometimes
EEPROM, too) looks like a NOR memory, ie, one can only write 0 bits, not 1
bits. When this is detected, either page erase is deployed (eg, with parts
that have PDI/UPDI interfaces), or if that is not available, both EEPROM
and flash caches are fully read in, a pgm->chip_erase() command is issued
and both EEPROM and flash are written back to the device. Hence, it can
take minutes to ensure that a single previously cleared bit is set and,
therefore, this routine should be called sparingly.
avr_chip_erase_cached() erases the chip and discards pending writes() to
flash or EEPROM. It presets the flash cache to all 0xff alleviating the
need to read from the device flash. However, if the programmer serves
bootloaders (pgm->prog_modes & PM_SPM) then the flash cache is reset
instead, necessitating flash memory be fetched from the device on first
read; the reason for this is that bootloaders emulate chip erase and they
won't overwrite themselves (some bootloaders, eg, optiboot ignore chip
erase commands altogether) making it truly unknowable what the flash
contents on device is after a chip erase.
For EEPROM avr_chip_erase_cached() concludes that it has been deleted if a
previously cached EEPROM page that contained cleared bits now no longer
has these clear bits on the device. Only with this evidence is the EEPROM
cache preset to all 0xff otherwise the cache discards all pending writes
to EEPROM and is left unchanged otherwise.
Finally, avr_reset_cache() resets the cache without synchronising pending
writes() to the device.
2022-10-05 21:16:15 +00:00
|
|
|
report_progress(1, -1, NULL);
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%s (dump): error reading %s address 0x%05lx of part %s\n",
|
2022-07-12 11:24:30 +00:00
|
|
|
progname, mem->desc, (long) addr + i, p->desc);
|
2002-01-12 01:26:09 +00:00
|
|
|
if (rc == -1)
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%*sread operation not supported on memory type %s\n",
|
2022-07-12 11:24:30 +00:00
|
|
|
(int) strlen(progname)+9, "", mem->desc);
|
2001-11-21 02:46:55 +00:00
|
|
|
return -1;
|
2001-11-19 17:44:24 +00:00
|
|
|
}
|
2022-03-31 20:21:49 +00:00
|
|
|
report_progress(i, len, NULL);
|
2001-11-19 17:44:24 +00:00
|
|
|
}
|
2022-03-31 20:21:49 +00:00
|
|
|
report_progress(1, 1, NULL);
|
2001-01-19 02:46:50 +00:00
|
|
|
|
|
|
|
hexdump_buf(stdout, addr, buf, len);
|
|
|
|
fprintf(stdout, "\n");
|
|
|
|
|
|
|
|
free(buf);
|
|
|
|
|
2001-11-21 02:46:55 +00:00
|
|
|
addr = addr + len;
|
|
|
|
|
2001-01-19 02:46:50 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2001-10-14 02:53:21 +00:00
|
|
|
|
2022-07-12 10:16:16 +00:00
|
|
|
static size_t maxstrlen(int argc, char **argv) {
|
|
|
|
size_t max = 0;
|
|
|
|
|
|
|
|
for(int i=0; i<argc; i++)
|
|
|
|
if(strlen(argv[i]) > max)
|
|
|
|
max = strlen(argv[i]);
|
|
|
|
|
|
|
|
return max;
|
|
|
|
}
|
|
|
|
|
2022-07-12 10:42:59 +00:00
|
|
|
|
|
|
|
// Change data item p of size bytes from big endian to little endian and vice versa
|
|
|
|
static void change_endian(void *p, int size) {
|
|
|
|
uint8_t tmp, *w = p;
|
|
|
|
|
|
|
|
for(int i=0; i<size/2; i++)
|
|
|
|
tmp = w[i], w[i] = w[size-i-1], w[size-i-1] = tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-07-12 11:01:14 +00:00
|
|
|
// Looks like a double mantissa in hex or dec notation
|
|
|
|
static int is_mantissa_only(char *p) {
|
|
|
|
char *digs;
|
|
|
|
|
|
|
|
if(*p == '+' || *p == '-')
|
|
|
|
p++;
|
|
|
|
|
|
|
|
if(*p == '0' && (p[1] == 'x' || p[1] == 'X')) {
|
|
|
|
p += 2;
|
|
|
|
digs = "0123456789abcdefABCDEF";
|
|
|
|
} else
|
|
|
|
digs = "0123456789";
|
|
|
|
|
|
|
|
if(!*p)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
while(*p)
|
|
|
|
if(!strchr(digs, *p++))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-10-11 13:40:37 +00:00
|
|
|
static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
2001-01-19 02:46:50 +00:00
|
|
|
if (argc < 4) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO,
|
2022-10-11 13:40:37 +00:00
|
|
|
"Usage: write <memory> <addr> <data>[,] {<data>[,]}\n"
|
2022-07-12 10:40:40 +00:00
|
|
|
" write <memory> <addr> <len> <data>[,] {<data>[,]} ...\n"
|
|
|
|
"\n"
|
|
|
|
"Ellipsis ... writes <len> bytes padded by repeating the last <data> item.\n"
|
|
|
|
"\n"
|
2022-07-14 16:13:13 +00:00
|
|
|
"<data> can be hexadecimal, octal or decimal integers, floating point numbers\n"
|
|
|
|
"or C-style strings and characters. For integers, an optional case-insensitive\n"
|
|
|
|
"suffix specifies the data size: HH 8 bit, H/S 16 bit, L 32 bit, LL 64 bit.\n"
|
|
|
|
"Suffix D indicates a 64-bit double, F a 32-bit float, whilst a floating point\n"
|
Provide cached byte-wise read/write API (#1106)
* Provide cached byte-wise read/write API
int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char *value);
int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char data);
int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p);
int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p);
int avr_reset_cache(const PROGRAMMER *pgm, const AVRPART *p);
avr_read_byte_cached() and avr_write_byte_cached() use a cache if paged
routines are available and if the device memory is EEPROM or flash,
otherwise they fall back to pgm->read_byte() and pgm->write_byte(),
respectively. Byte-wise cached read always gets its data from the cache,
possibly after reading a page from the device memory. Byte-wise cached
write with an address in memory range only ever modifies the cache. Any
modifications are written to the device after calling avr_flush_cache() or
when attempting to read or write from a location outside the address range
of the device memory.
avr_flush_cache() synchronises pending writes to EEPROM and flash with the
device. With some programmer and part combinations, flash (and sometimes
EEPROM, too) looks like a NOR memory, ie, one can only write 0 bits, not 1
bits. When this is detected, either page erase is deployed (eg, with parts
that have PDI/UPDI interfaces), or if that is not available, both EEPROM
and flash caches are fully read in, a pgm->chip_erase() command is issued
and both EEPROM and flash are written back to the device. Hence, it can
take minutes to ensure that a single previously cleared bit is set and,
therefore, this routine should be called sparingly.
avr_chip_erase_cached() erases the chip and discards pending writes() to
flash or EEPROM. It presets the flash cache to all 0xff alleviating the
need to read from the device flash. However, if the programmer serves
bootloaders (pgm->prog_modes & PM_SPM) then the flash cache is reset
instead, necessitating flash memory be fetched from the device on first
read; the reason for this is that bootloaders emulate chip erase and they
won't overwrite themselves (some bootloaders, eg, optiboot ignore chip
erase commands altogether) making it truly unknowable what the flash
contents on device is after a chip erase.
For EEPROM avr_chip_erase_cached() concludes that it has been deleted if a
previously cached EEPROM page that contained cleared bits now no longer
has these clear bits on the device. Only with this evidence is the EEPROM
cache preset to all 0xff otherwise the cache discards all pending writes
to EEPROM and is left unchanged otherwise.
Finally, avr_reset_cache() resets the cache without synchronising pending
writes() to the device.
2022-10-05 21:16:15 +00:00
|
|
|
"number without suffix defaults to 32-bit float. Hexadecimal floating point\n"
|
2022-07-14 16:13:13 +00:00
|
|
|
"notation is supported. An ambiguous trailing suffix, eg, 0x1.8D, is read as\n"
|
|
|
|
"no-suffix float where D is part of the mantissa; use a zero exponent 0x1.8p0D\n"
|
|
|
|
"to clarify.\n"
|
2022-07-12 10:40:40 +00:00
|
|
|
"\n"
|
2022-07-14 16:13:13 +00:00
|
|
|
"An optional U suffix makes integers unsigned. Ordinary 0x hex integers are\n"
|
2022-07-12 10:40:40 +00:00
|
|
|
"always treated as unsigned. +0x or -0x hex numbers are treated as signed\n"
|
|
|
|
"unless they have a U suffix. Unsigned integers cannot be larger than 2^64-1.\n"
|
|
|
|
"If n is an unsigned integer then -n is also a valid unsigned integer as in C.\n"
|
|
|
|
"Signed integers must fall into the [-2^63, 2^63-1] range or a correspondingly\n"
|
|
|
|
"smaller range when a suffix specifies a smaller type. Out of range signed\n"
|
|
|
|
"numbers trigger a warning.\n"
|
|
|
|
"\n"
|
2022-07-14 16:13:13 +00:00
|
|
|
"Ordinary 0x hex integers with n hex digits (counting leading zeros) use the\n"
|
|
|
|
"smallest size of 1, 2, 4 and 8 bytes that can accommodate any n-digit hex\n"
|
|
|
|
"integer. If an integer suffix specifies a size explicitly the corresponding\n"
|
|
|
|
"number of least significant bytes are written. Otherwise, signed and unsigned\n"
|
|
|
|
"integers alike occupy the smallest of 1, 2, 4, or 8 bytes needed to\n"
|
|
|
|
"accommodate them in their respective representation.\n"
|
2022-07-12 10:40:40 +00:00
|
|
|
);
|
2001-01-19 02:46:50 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2022-07-12 10:59:42 +00:00
|
|
|
int i;
|
2022-02-20 18:08:30 +00:00
|
|
|
uint8_t write_mode; // Operation mode, "standard" or "fill"
|
|
|
|
uint8_t start_offset; // Which argc argument
|
2022-07-12 10:59:42 +00:00
|
|
|
int len; // Number of bytes to write to memory
|
2022-10-11 13:40:37 +00:00
|
|
|
char *memtype = argv[1]; // Memory name string
|
|
|
|
AVRMEM *mem = avr_locate_mem(p, memtype);
|
2001-11-21 02:46:55 +00:00
|
|
|
if (mem == NULL) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%s (write): %s memory type not defined for part %s\n",
|
2022-07-12 11:24:30 +00:00
|
|
|
progname, memtype, p->desc);
|
2001-01-19 02:46:50 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2022-07-12 10:59:42 +00:00
|
|
|
int maxsize = mem->size;
|
2001-01-19 02:46:50 +00:00
|
|
|
|
2022-10-11 13:40:37 +00:00
|
|
|
char *end_ptr;
|
2022-07-12 10:59:42 +00:00
|
|
|
int addr = strtoul(argv[2], &end_ptr, 0);
|
2022-02-20 18:08:30 +00:00
|
|
|
if (*end_ptr || (end_ptr == argv[2])) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%s (write): can't parse address %s\n",
|
2022-07-12 10:58:51 +00:00
|
|
|
progname, argv[2]);
|
2001-01-19 02:46:50 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2022-10-11 13:40:37 +00:00
|
|
|
if (addr < 0 || addr >= maxsize) {
|
|
|
|
terminal_message(MSG_INFO, "%s (write): %s address 0x%05x is out of range [0, 0x%05x]\n",
|
|
|
|
progname, mem->desc, addr, maxsize);
|
2001-01-19 02:46:50 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2022-04-09 18:08:44 +00:00
|
|
|
// Allocate a buffer guaranteed to be large enough
|
2022-10-11 13:40:37 +00:00
|
|
|
uint8_t *buf = calloc(mem->size + 8 + maxstrlen(argc-3, argv+3)+1, sizeof(uint8_t));
|
2022-03-03 18:37:42 +00:00
|
|
|
if (buf == NULL) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%s (write): out of memory\n", progname);
|
2022-03-03 18:37:42 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find the first argument to write to flash and how many arguments to parse and write
|
2022-02-17 21:40:26 +00:00
|
|
|
if (strcmp(argv[argc - 1], "...") == 0) {
|
2022-02-17 10:24:59 +00:00
|
|
|
write_mode = WRITE_MODE_FILL;
|
2022-03-03 18:37:42 +00:00
|
|
|
start_offset = 4;
|
2022-02-20 18:08:30 +00:00
|
|
|
len = strtoul(argv[3], &end_ptr, 0);
|
|
|
|
if (*end_ptr || (end_ptr == argv[3])) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%s (write ...): can't parse length %s\n",
|
2022-07-12 10:58:51 +00:00
|
|
|
progname, argv[3]);
|
2022-03-18 20:20:58 +00:00
|
|
|
free(buf);
|
2022-02-17 10:24:59 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
write_mode = WRITE_MODE_STANDARD;
|
2022-03-03 18:37:42 +00:00
|
|
|
start_offset = 3;
|
2022-02-17 21:40:26 +00:00
|
|
|
len = argc - start_offset;
|
2022-02-17 12:00:30 +00:00
|
|
|
}
|
|
|
|
|
2022-02-19 22:34:50 +00:00
|
|
|
// Structure related to data that is being written to memory
|
|
|
|
struct Data {
|
|
|
|
// Data info
|
2022-07-12 10:59:42 +00:00
|
|
|
int bytes_grown;
|
2022-02-19 22:34:50 +00:00
|
|
|
uint8_t size;
|
2022-07-13 10:19:21 +00:00
|
|
|
char *str_ptr;
|
2022-02-19 22:34:50 +00:00
|
|
|
// Data union
|
|
|
|
union {
|
|
|
|
float f;
|
2022-07-12 10:36:57 +00:00
|
|
|
double d;
|
2022-02-19 22:34:50 +00:00
|
|
|
int64_t ll;
|
Remodel logic of the size that integer items occupy in terminal write
Integers can be hexadecimal, decimal or octal. An optional case-insensitive
suffix specifies their size: HH: 8 bit, H/S: 16 bit, L: 32 bit, LL: 64 bit
An optional U suffix makes a number unsigned. Ordinary 0x hex numbers are
always treated as unsigned. +0x or -0x hex numbers are treated as signed
unless they have a U suffix. Unsigned integers cannot be larger than 2^64-1.
If n is an unsigned integer then -n is also a valid unsigned integer as in C.
Signed integers must fall into the [-2^63, 2^63-1] range or a correspondingly
smaller range when a suffix specifies a smaller type. Out of range signed
numbers trigger a warning.
Ordinary 0x hex numbers with n hex digits (counting leading zeros) use
the smallest size of 1, 2, 4 and 8 bytes that can accommodate any n-digit hex
number. If a suffix specifies a size explicitly the corresponding number of
least significant bytes are written. Otherwise, signed and unsigned integers
alike occupy the smallest of 1, 2, 4, or 8 bytes needed to accommodate them
in their respective representation.
2022-07-12 10:32:38 +00:00
|
|
|
uint64_t ull;
|
2022-07-14 16:13:13 +00:00
|
|
|
uint8_t a[8];
|
2022-02-19 22:34:50 +00:00
|
|
|
};
|
2022-04-01 18:35:18 +00:00
|
|
|
} data = {
|
|
|
|
.bytes_grown = 0,
|
|
|
|
.size = 0,
|
|
|
|
.str_ptr = NULL,
|
2022-07-12 10:42:59 +00:00
|
|
|
.ull = 1
|
2022-04-01 18:35:18 +00:00
|
|
|
};
|
2022-02-19 19:15:52 +00:00
|
|
|
|
2022-07-12 10:42:59 +00:00
|
|
|
if(sizeof(long long) != sizeof(int64_t) || (data.a[0]^data.a[7]) != 1)
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%s (write): assumption on data types not met? "
|
2022-07-12 10:58:51 +00:00
|
|
|
"Check source and recompile\n", progname);
|
2022-07-12 10:42:59 +00:00
|
|
|
bool is_big_endian = data.a[7];
|
|
|
|
|
2022-03-02 19:09:59 +00:00
|
|
|
for (i = start_offset; i < len + start_offset; i++) {
|
2022-02-17 21:40:26 +00:00
|
|
|
// Handle the next argument
|
|
|
|
if (i < argc - start_offset + 3) {
|
2022-07-12 10:12:20 +00:00
|
|
|
char *argi = argv[i];
|
|
|
|
size_t arglen = strlen(argi);
|
|
|
|
|
2022-07-12 10:15:30 +00:00
|
|
|
data.size = 0;
|
|
|
|
|
2022-04-04 07:38:02 +00:00
|
|
|
// Free string pointer if already allocated
|
|
|
|
if(data.str_ptr) {
|
|
|
|
free(data.str_ptr);
|
|
|
|
data.str_ptr = NULL;
|
|
|
|
}
|
|
|
|
|
2022-07-12 11:02:33 +00:00
|
|
|
// Remove trailing comma to allow cut and paste of lists
|
2022-07-12 10:39:52 +00:00
|
|
|
if(arglen > 0 && argi[arglen-1] == ',')
|
|
|
|
argi[--arglen] = 0;
|
|
|
|
|
Remodel logic of the size that integer items occupy in terminal write
Integers can be hexadecimal, decimal or octal. An optional case-insensitive
suffix specifies their size: HH: 8 bit, H/S: 16 bit, L: 32 bit, LL: 64 bit
An optional U suffix makes a number unsigned. Ordinary 0x hex numbers are
always treated as unsigned. +0x or -0x hex numbers are treated as signed
unless they have a U suffix. Unsigned integers cannot be larger than 2^64-1.
If n is an unsigned integer then -n is also a valid unsigned integer as in C.
Signed integers must fall into the [-2^63, 2^63-1] range or a correspondingly
smaller range when a suffix specifies a smaller type. Out of range signed
numbers trigger a warning.
Ordinary 0x hex numbers with n hex digits (counting leading zeros) use
the smallest size of 1, 2, 4 and 8 bytes that can accommodate any n-digit hex
number. If a suffix specifies a size explicitly the corresponding number of
least significant bytes are written. Otherwise, signed and unsigned integers
alike occupy the smallest of 1, 2, 4, or 8 bytes needed to accommodate them
in their respective representation.
2022-07-12 10:32:38 +00:00
|
|
|
// Try integers and assign data size
|
|
|
|
errno = 0;
|
|
|
|
data.ull = strtoull(argi, &end_ptr, 0);
|
|
|
|
if (!(end_ptr == argi || errno)) {
|
|
|
|
unsigned int nu=0, nl=0, nh=0, ns=0, nx=0;
|
|
|
|
char *p;
|
|
|
|
|
2022-07-12 11:02:33 +00:00
|
|
|
// Parse suffixes: ULL, LL, UL, L ... UHH, HH
|
Remodel logic of the size that integer items occupy in terminal write
Integers can be hexadecimal, decimal or octal. An optional case-insensitive
suffix specifies their size: HH: 8 bit, H/S: 16 bit, L: 32 bit, LL: 64 bit
An optional U suffix makes a number unsigned. Ordinary 0x hex numbers are
always treated as unsigned. +0x or -0x hex numbers are treated as signed
unless they have a U suffix. Unsigned integers cannot be larger than 2^64-1.
If n is an unsigned integer then -n is also a valid unsigned integer as in C.
Signed integers must fall into the [-2^63, 2^63-1] range or a correspondingly
smaller range when a suffix specifies a smaller type. Out of range signed
numbers trigger a warning.
Ordinary 0x hex numbers with n hex digits (counting leading zeros) use
the smallest size of 1, 2, 4 and 8 bytes that can accommodate any n-digit hex
number. If a suffix specifies a size explicitly the corresponding number of
least significant bytes are written. Otherwise, signed and unsigned integers
alike occupy the smallest of 1, 2, 4, or 8 bytes needed to accommodate them
in their respective representation.
2022-07-12 10:32:38 +00:00
|
|
|
for(p=end_ptr; *p; p++)
|
|
|
|
switch(toupper(*p)) {
|
|
|
|
case 'U': nu++; break;
|
|
|
|
case 'L': nl++; break;
|
|
|
|
case 'H': nh++; break;
|
|
|
|
case 'S': ns++; break;
|
|
|
|
default: nx++;
|
|
|
|
}
|
|
|
|
|
2022-07-12 11:02:33 +00:00
|
|
|
if(nx==0 && nu<2 && nl<3 && nh<3 && ns<2) { // Could be valid integer suffix
|
|
|
|
if(nu==0 || toupper(*end_ptr) == 'U' || toupper(p[-1]) == 'U') { // If U, then must be at start or end
|
|
|
|
bool is_hex = strncasecmp(argi, "0x", 2) == 0; // Ordinary hex: 0x... without explicit +/- sign
|
|
|
|
bool is_signed = !(nu || is_hex); // Neither explicitly unsigned nor ordinary hex
|
Remodel logic of the size that integer items occupy in terminal write
Integers can be hexadecimal, decimal or octal. An optional case-insensitive
suffix specifies their size: HH: 8 bit, H/S: 16 bit, L: 32 bit, LL: 64 bit
An optional U suffix makes a number unsigned. Ordinary 0x hex numbers are
always treated as unsigned. +0x or -0x hex numbers are treated as signed
unless they have a U suffix. Unsigned integers cannot be larger than 2^64-1.
If n is an unsigned integer then -n is also a valid unsigned integer as in C.
Signed integers must fall into the [-2^63, 2^63-1] range or a correspondingly
smaller range when a suffix specifies a smaller type. Out of range signed
numbers trigger a warning.
Ordinary 0x hex numbers with n hex digits (counting leading zeros) use
the smallest size of 1, 2, 4 and 8 bytes that can accommodate any n-digit hex
number. If a suffix specifies a size explicitly the corresponding number of
least significant bytes are written. Otherwise, signed and unsigned integers
alike occupy the smallest of 1, 2, 4, or 8 bytes needed to accommodate them
in their respective representation.
2022-07-12 10:32:38 +00:00
|
|
|
bool is_outside_int64_t = 0;
|
|
|
|
bool is_out_of_range = 0;
|
|
|
|
int nhexdigs = p-argi-2;
|
|
|
|
|
|
|
|
if(is_signed) { // Is input in range for int64_t?
|
|
|
|
errno = 0; (void) strtoll(argi, NULL, 0);
|
|
|
|
is_outside_int64_t = errno == ERANGE;
|
|
|
|
}
|
|
|
|
|
2022-07-12 11:02:33 +00:00
|
|
|
if(nl==0 && ns==0 && nh==0) { // No explicit data size
|
|
|
|
// Ordinary hex numbers have implicit size given by number of hex digits, including leading zeros
|
Remodel logic of the size that integer items occupy in terminal write
Integers can be hexadecimal, decimal or octal. An optional case-insensitive
suffix specifies their size: HH: 8 bit, H/S: 16 bit, L: 32 bit, LL: 64 bit
An optional U suffix makes a number unsigned. Ordinary 0x hex numbers are
always treated as unsigned. +0x or -0x hex numbers are treated as signed
unless they have a U suffix. Unsigned integers cannot be larger than 2^64-1.
If n is an unsigned integer then -n is also a valid unsigned integer as in C.
Signed integers must fall into the [-2^63, 2^63-1] range or a correspondingly
smaller range when a suffix specifies a smaller type. Out of range signed
numbers trigger a warning.
Ordinary 0x hex numbers with n hex digits (counting leading zeros) use
the smallest size of 1, 2, 4 and 8 bytes that can accommodate any n-digit hex
number. If a suffix specifies a size explicitly the corresponding number of
least significant bytes are written. Otherwise, signed and unsigned integers
alike occupy the smallest of 1, 2, 4, or 8 bytes needed to accommodate them
in their respective representation.
2022-07-12 10:32:38 +00:00
|
|
|
if(is_hex) {
|
|
|
|
data.size = nhexdigs > 8? 8: nhexdigs > 4? 4: nhexdigs > 2? 2: 1;
|
|
|
|
|
|
|
|
} else if(is_signed) {
|
2022-07-12 11:02:33 +00:00
|
|
|
// Smallest size that fits signed representation
|
Remodel logic of the size that integer items occupy in terminal write
Integers can be hexadecimal, decimal or octal. An optional case-insensitive
suffix specifies their size: HH: 8 bit, H/S: 16 bit, L: 32 bit, LL: 64 bit
An optional U suffix makes a number unsigned. Ordinary 0x hex numbers are
always treated as unsigned. +0x or -0x hex numbers are treated as signed
unless they have a U suffix. Unsigned integers cannot be larger than 2^64-1.
If n is an unsigned integer then -n is also a valid unsigned integer as in C.
Signed integers must fall into the [-2^63, 2^63-1] range or a correspondingly
smaller range when a suffix specifies a smaller type. Out of range signed
numbers trigger a warning.
Ordinary 0x hex numbers with n hex digits (counting leading zeros) use
the smallest size of 1, 2, 4 and 8 bytes that can accommodate any n-digit hex
number. If a suffix specifies a size explicitly the corresponding number of
least significant bytes are written. Otherwise, signed and unsigned integers
alike occupy the smallest of 1, 2, 4, or 8 bytes needed to accommodate them
in their respective representation.
2022-07-12 10:32:38 +00:00
|
|
|
data.size =
|
|
|
|
is_outside_int64_t? 8:
|
|
|
|
data.ll < INT32_MIN || data.ll > INT32_MAX? 8:
|
|
|
|
data.ll < INT16_MIN || data.ll > INT16_MAX? 4:
|
|
|
|
data.ll < INT8_MIN || data.ll > INT8_MAX? 2: 1;
|
|
|
|
|
|
|
|
} else {
|
2022-07-12 11:02:33 +00:00
|
|
|
// Smallest size that fits unsigned representation
|
Remodel logic of the size that integer items occupy in terminal write
Integers can be hexadecimal, decimal or octal. An optional case-insensitive
suffix specifies their size: HH: 8 bit, H/S: 16 bit, L: 32 bit, LL: 64 bit
An optional U suffix makes a number unsigned. Ordinary 0x hex numbers are
always treated as unsigned. +0x or -0x hex numbers are treated as signed
unless they have a U suffix. Unsigned integers cannot be larger than 2^64-1.
If n is an unsigned integer then -n is also a valid unsigned integer as in C.
Signed integers must fall into the [-2^63, 2^63-1] range or a correspondingly
smaller range when a suffix specifies a smaller type. Out of range signed
numbers trigger a warning.
Ordinary 0x hex numbers with n hex digits (counting leading zeros) use
the smallest size of 1, 2, 4 and 8 bytes that can accommodate any n-digit hex
number. If a suffix specifies a size explicitly the corresponding number of
least significant bytes are written. Otherwise, signed and unsigned integers
alike occupy the smallest of 1, 2, 4, or 8 bytes needed to accommodate them
in their respective representation.
2022-07-12 10:32:38 +00:00
|
|
|
data.size =
|
|
|
|
data.ull > UINT32_MAX? 8:
|
|
|
|
data.ull > UINT16_MAX? 4:
|
|
|
|
data.ull > UINT8_MAX? 2: 1;
|
|
|
|
}
|
|
|
|
} else if(nl==0 && nh==2 && ns==0) { // HH
|
|
|
|
data.size = 1;
|
|
|
|
if(is_outside_int64_t || (is_signed && (data.ll < INT8_MIN || data.ll > INT8_MAX))) {
|
|
|
|
is_out_of_range = 1;
|
|
|
|
data.ll = (int8_t) data.ll;
|
|
|
|
}
|
|
|
|
} else if(nl==0 && ((nh==1 && ns==0) || (nh==0 && ns==1))) { // H or S
|
|
|
|
data.size = 2;
|
|
|
|
if(is_outside_int64_t || (is_signed && (data.ll < INT16_MIN || data.ll > INT16_MAX))) {
|
|
|
|
is_out_of_range = 1;
|
|
|
|
data.ll = (int16_t) data.ll;
|
|
|
|
}
|
|
|
|
} else if(nl==1 && nh==0 && ns==0) { // L
|
|
|
|
data.size = 4;
|
|
|
|
if(is_outside_int64_t || (is_signed && (data.ll < INT32_MIN || data.ll > INT32_MAX))) {
|
|
|
|
is_out_of_range = 1;
|
|
|
|
data.ll = (int32_t) data.ll;
|
|
|
|
}
|
|
|
|
} else if(nl==2 && nh==0 && ns==0) { // LL
|
|
|
|
data.size = 8;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(is_outside_int64_t || is_out_of_range)
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%s (write): %s out of int%d_t range, "
|
2022-07-12 10:58:51 +00:00
|
|
|
"interpreted as %d-byte %lld; consider 'U' suffix\n",
|
|
|
|
progname, argi, data.size*8, data.size, data.ll);
|
Remodel logic of the size that integer items occupy in terminal write
Integers can be hexadecimal, decimal or octal. An optional case-insensitive
suffix specifies their size: HH: 8 bit, H/S: 16 bit, L: 32 bit, LL: 64 bit
An optional U suffix makes a number unsigned. Ordinary 0x hex numbers are
always treated as unsigned. +0x or -0x hex numbers are treated as signed
unless they have a U suffix. Unsigned integers cannot be larger than 2^64-1.
If n is an unsigned integer then -n is also a valid unsigned integer as in C.
Signed integers must fall into the [-2^63, 2^63-1] range or a correspondingly
smaller range when a suffix specifies a smaller type. Out of range signed
numbers trigger a warning.
Ordinary 0x hex numbers with n hex digits (counting leading zeros) use
the smallest size of 1, 2, 4 and 8 bytes that can accommodate any n-digit hex
number. If a suffix specifies a size explicitly the corresponding number of
least significant bytes are written. Otherwise, signed and unsigned integers
alike occupy the smallest of 1, 2, 4, or 8 bytes needed to accommodate them
in their respective representation.
2022-07-12 10:32:38 +00:00
|
|
|
}
|
2022-07-12 10:12:20 +00:00
|
|
|
}
|
2022-02-19 22:34:50 +00:00
|
|
|
}
|
2022-02-20 18:08:30 +00:00
|
|
|
|
2022-07-14 16:13:13 +00:00
|
|
|
if(!data.size) { // Try double now that input was rejected as integer
|
2022-07-12 11:01:14 +00:00
|
|
|
data.d = strtod(argi, &end_ptr);
|
2022-07-14 16:13:13 +00:00
|
|
|
if (end_ptr != argi && toupper(*end_ptr) == 'D' && end_ptr[1] == 0)
|
|
|
|
data.size = 8;
|
2022-07-12 11:01:14 +00:00
|
|
|
}
|
|
|
|
|
2022-07-12 10:36:57 +00:00
|
|
|
if(!data.size) { // Try float
|
2022-07-12 10:12:20 +00:00
|
|
|
data.f = strtof(argi, &end_ptr);
|
2022-07-12 10:36:57 +00:00
|
|
|
if (end_ptr != argi && toupper(*end_ptr) == 'F' && end_ptr[1] == 0)
|
Remodel logic of the size that integer items occupy in terminal write
Integers can be hexadecimal, decimal or octal. An optional case-insensitive
suffix specifies their size: HH: 8 bit, H/S: 16 bit, L: 32 bit, LL: 64 bit
An optional U suffix makes a number unsigned. Ordinary 0x hex numbers are
always treated as unsigned. +0x or -0x hex numbers are treated as signed
unless they have a U suffix. Unsigned integers cannot be larger than 2^64-1.
If n is an unsigned integer then -n is also a valid unsigned integer as in C.
Signed integers must fall into the [-2^63, 2^63-1] range or a correspondingly
smaller range when a suffix specifies a smaller type. Out of range signed
numbers trigger a warning.
Ordinary 0x hex numbers with n hex digits (counting leading zeros) use
the smallest size of 1, 2, 4 and 8 bytes that can accommodate any n-digit hex
number. If a suffix specifies a size explicitly the corresponding number of
least significant bytes are written. Otherwise, signed and unsigned integers
alike occupy the smallest of 1, 2, 4, or 8 bytes needed to accommodate them
in their respective representation.
2022-07-12 10:32:38 +00:00
|
|
|
data.size = 4;
|
2022-07-14 16:13:13 +00:00
|
|
|
if (end_ptr != argi && *end_ptr == 0) // no suffix defaults to float but ...
|
|
|
|
// ... do not accept valid mantissa-only floats that are integer rejects (eg, 078 or ULL overflows)
|
|
|
|
if (!is_mantissa_only(argi))
|
|
|
|
data.size = 4;
|
2022-07-12 10:36:57 +00:00
|
|
|
}
|
|
|
|
|
2022-07-15 17:50:20 +00:00
|
|
|
if(!data.size && arglen > 1) { // Try C-style string or single character
|
2022-07-12 10:39:02 +00:00
|
|
|
if ((*argi == '\'' && argi[arglen-1] == '\'') || (*argi == '\"' && argi[arglen-1] == '\"')) {
|
|
|
|
char *s = calloc(arglen-1, 1);
|
|
|
|
if (s == NULL) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%s (write str): out of memory\n", progname);
|
2022-02-17 21:40:26 +00:00
|
|
|
free(buf);
|
|
|
|
return -1;
|
|
|
|
}
|
2022-07-12 10:39:02 +00:00
|
|
|
// Strip start and end quotes, and unescape C string
|
|
|
|
strncpy(s, argi+1, arglen-2);
|
2022-08-09 20:20:44 +00:00
|
|
|
cfg_unescape(s, s);
|
2022-07-12 11:02:33 +00:00
|
|
|
if (*argi == '\'') { // Single C-style character
|
2022-07-12 10:39:02 +00:00
|
|
|
if(*s && s[1])
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%s (write): only using first character of %s\n",
|
2022-07-12 10:58:51 +00:00
|
|
|
progname, argi);
|
2022-07-12 10:39:02 +00:00
|
|
|
data.ll = *s;
|
|
|
|
data.size = 1;
|
|
|
|
free(s);
|
|
|
|
} else { // C-style string
|
|
|
|
data.str_ptr = s;
|
|
|
|
}
|
|
|
|
}
|
2022-02-17 10:24:59 +00:00
|
|
|
}
|
2022-07-12 11:01:14 +00:00
|
|
|
|
|
|
|
if(!data.size && !data.str_ptr) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%s (write): can't parse data %s\n",
|
2022-07-12 11:01:14 +00:00
|
|
|
progname, argi);
|
|
|
|
free(buf);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Assume endianness is the same for double and int, and ensure little endian representation
|
2022-07-12 10:42:59 +00:00
|
|
|
if(is_big_endian && data.size > 1)
|
|
|
|
change_endian(data.a, data.size);
|
2001-01-19 02:46:50 +00:00
|
|
|
}
|
2022-07-12 10:39:02 +00:00
|
|
|
|
2022-04-01 20:23:55 +00:00
|
|
|
if(data.str_ptr) {
|
2022-07-12 10:59:42 +00:00
|
|
|
for(size_t j = 0; j < strlen(data.str_ptr); j++)
|
2022-04-01 18:35:18 +00:00
|
|
|
buf[i - start_offset + data.bytes_grown++] = (uint8_t)data.str_ptr[j];
|
2022-07-13 11:25:09 +00:00
|
|
|
} else if(data.size > 0) {
|
|
|
|
for(int k=0; k<data.size; k++)
|
|
|
|
buf[i - start_offset + data.bytes_grown + k] = data.a[k];
|
|
|
|
data.bytes_grown += data.size-1;
|
2001-01-19 02:46:50 +00:00
|
|
|
}
|
2022-04-09 18:08:44 +00:00
|
|
|
|
|
|
|
// Make sure buf does not overflow
|
|
|
|
if (i - start_offset + data.bytes_grown > maxsize)
|
|
|
|
break;
|
2001-01-19 02:46:50 +00:00
|
|
|
}
|
|
|
|
|
2022-02-17 21:40:26 +00:00
|
|
|
// When in "fill" mode, the maximum size is already predefined
|
|
|
|
if (write_mode == WRITE_MODE_FILL)
|
2022-02-19 22:34:50 +00:00
|
|
|
data.bytes_grown = 0;
|
2022-02-17 21:40:26 +00:00
|
|
|
|
2022-02-19 22:34:50 +00:00
|
|
|
if ((addr + len + data.bytes_grown) > maxsize) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%s (write): selected address and # bytes exceed "
|
2022-07-12 10:58:51 +00:00
|
|
|
"range for %s memory\n", progname, memtype);
|
2022-03-18 20:20:58 +00:00
|
|
|
free(buf);
|
2022-02-17 21:40:26 +00:00
|
|
|
return -1;
|
2001-01-19 02:46:50 +00:00
|
|
|
}
|
2001-11-19 17:44:24 +00:00
|
|
|
|
2022-04-04 07:38:02 +00:00
|
|
|
if(data.str_ptr)
|
|
|
|
free(data.str_ptr);
|
|
|
|
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_NOTICE, "Info: writing %d bytes starting from address 0x%02lx",
|
2022-07-12 10:58:51 +00:00
|
|
|
len + data.bytes_grown, (long) addr);
|
2022-03-18 20:19:36 +00:00
|
|
|
if (write_mode == WRITE_MODE_FILL)
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_NOTICE, "; remaining space filled with %s", argv[argc - 2]);
|
|
|
|
terminal_message(MSG_NOTICE, "\n");
|
2022-03-18 20:19:36 +00:00
|
|
|
|
2002-11-30 14:09:12 +00:00
|
|
|
pgm->err_led(pgm, OFF);
|
2022-02-20 18:08:30 +00:00
|
|
|
bool werror = false;
|
Provide cached byte-wise read/write API (#1106)
* Provide cached byte-wise read/write API
int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char *value);
int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char data);
int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p);
int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p);
int avr_reset_cache(const PROGRAMMER *pgm, const AVRPART *p);
avr_read_byte_cached() and avr_write_byte_cached() use a cache if paged
routines are available and if the device memory is EEPROM or flash,
otherwise they fall back to pgm->read_byte() and pgm->write_byte(),
respectively. Byte-wise cached read always gets its data from the cache,
possibly after reading a page from the device memory. Byte-wise cached
write with an address in memory range only ever modifies the cache. Any
modifications are written to the device after calling avr_flush_cache() or
when attempting to read or write from a location outside the address range
of the device memory.
avr_flush_cache() synchronises pending writes to EEPROM and flash with the
device. With some programmer and part combinations, flash (and sometimes
EEPROM, too) looks like a NOR memory, ie, one can only write 0 bits, not 1
bits. When this is detected, either page erase is deployed (eg, with parts
that have PDI/UPDI interfaces), or if that is not available, both EEPROM
and flash caches are fully read in, a pgm->chip_erase() command is issued
and both EEPROM and flash are written back to the device. Hence, it can
take minutes to ensure that a single previously cleared bit is set and,
therefore, this routine should be called sparingly.
avr_chip_erase_cached() erases the chip and discards pending writes() to
flash or EEPROM. It presets the flash cache to all 0xff alleviating the
need to read from the device flash. However, if the programmer serves
bootloaders (pgm->prog_modes & PM_SPM) then the flash cache is reset
instead, necessitating flash memory be fetched from the device on first
read; the reason for this is that bootloaders emulate chip erase and they
won't overwrite themselves (some bootloaders, eg, optiboot ignore chip
erase commands altogether) making it truly unknowable what the flash
contents on device is after a chip erase.
For EEPROM avr_chip_erase_cached() concludes that it has been deleted if a
previously cached EEPROM page that contained cleared bits now no longer
has these clear bits on the device. Only with this evidence is the EEPROM
cache preset to all 0xff otherwise the cache discards all pending writes
to EEPROM and is left unchanged otherwise.
Finally, avr_reset_cache() resets the cache without synchronising pending
writes() to the device.
2022-10-05 21:16:15 +00:00
|
|
|
report_progress(0, 1, avr_has_paged_access(pgm, mem)? "Caching": "Writing");
|
|
|
|
for (i = 0; i < len + data.bytes_grown; i++) {
|
|
|
|
int rc = pgm->write_byte_cached(pgm, p, mem, addr+i, buf[i]);
|
2001-01-22 01:59:47 +00:00
|
|
|
if (rc) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%s (write): error writing 0x%02x at 0x%05lx, rc=%d\n",
|
2022-07-12 10:58:51 +00:00
|
|
|
progname, buf[i], (long) addr+i, (int) rc);
|
2002-01-12 01:26:09 +00:00
|
|
|
if (rc == -1)
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%*swrite operation not supported on memory type %s\n",
|
2022-07-12 11:24:30 +00:00
|
|
|
(int) strlen(progname)+10, "", mem->desc);
|
2022-02-20 18:08:30 +00:00
|
|
|
werror = true;
|
2001-02-08 01:05:05 +00:00
|
|
|
}
|
2002-02-14 02:48:07 +00:00
|
|
|
|
2022-02-20 18:08:30 +00:00
|
|
|
uint8_t b;
|
Provide cached byte-wise read/write API (#1106)
* Provide cached byte-wise read/write API
int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char *value);
int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char data);
int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p);
int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p);
int avr_reset_cache(const PROGRAMMER *pgm, const AVRPART *p);
avr_read_byte_cached() and avr_write_byte_cached() use a cache if paged
routines are available and if the device memory is EEPROM or flash,
otherwise they fall back to pgm->read_byte() and pgm->write_byte(),
respectively. Byte-wise cached read always gets its data from the cache,
possibly after reading a page from the device memory. Byte-wise cached
write with an address in memory range only ever modifies the cache. Any
modifications are written to the device after calling avr_flush_cache() or
when attempting to read or write from a location outside the address range
of the device memory.
avr_flush_cache() synchronises pending writes to EEPROM and flash with the
device. With some programmer and part combinations, flash (and sometimes
EEPROM, too) looks like a NOR memory, ie, one can only write 0 bits, not 1
bits. When this is detected, either page erase is deployed (eg, with parts
that have PDI/UPDI interfaces), or if that is not available, both EEPROM
and flash caches are fully read in, a pgm->chip_erase() command is issued
and both EEPROM and flash are written back to the device. Hence, it can
take minutes to ensure that a single previously cleared bit is set and,
therefore, this routine should be called sparingly.
avr_chip_erase_cached() erases the chip and discards pending writes() to
flash or EEPROM. It presets the flash cache to all 0xff alleviating the
need to read from the device flash. However, if the programmer serves
bootloaders (pgm->prog_modes & PM_SPM) then the flash cache is reset
instead, necessitating flash memory be fetched from the device on first
read; the reason for this is that bootloaders emulate chip erase and they
won't overwrite themselves (some bootloaders, eg, optiboot ignore chip
erase commands altogether) making it truly unknowable what the flash
contents on device is after a chip erase.
For EEPROM avr_chip_erase_cached() concludes that it has been deleted if a
previously cached EEPROM page that contained cleared bits now no longer
has these clear bits on the device. Only with this evidence is the EEPROM
cache preset to all 0xff otherwise the cache discards all pending writes
to EEPROM and is left unchanged otherwise.
Finally, avr_reset_cache() resets the cache without synchronising pending
writes() to the device.
2022-10-05 21:16:15 +00:00
|
|
|
rc = pgm->read_byte_cached(pgm, p, mem, addr+i, &b);
|
2002-02-14 02:48:07 +00:00
|
|
|
if (b != buf[i]) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%s (write): error writing 0x%02x at 0x%05lx cell=0x%02x\n",
|
2022-07-12 10:58:51 +00:00
|
|
|
progname, buf[i], (long) addr+i, b);
|
2022-02-20 18:08:30 +00:00
|
|
|
werror = true;
|
2002-02-14 02:48:07 +00:00
|
|
|
}
|
|
|
|
|
Provide cached byte-wise read/write API (#1106)
* Provide cached byte-wise read/write API
int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char *value);
int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char data);
int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p);
int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p);
int avr_reset_cache(const PROGRAMMER *pgm, const AVRPART *p);
avr_read_byte_cached() and avr_write_byte_cached() use a cache if paged
routines are available and if the device memory is EEPROM or flash,
otherwise they fall back to pgm->read_byte() and pgm->write_byte(),
respectively. Byte-wise cached read always gets its data from the cache,
possibly after reading a page from the device memory. Byte-wise cached
write with an address in memory range only ever modifies the cache. Any
modifications are written to the device after calling avr_flush_cache() or
when attempting to read or write from a location outside the address range
of the device memory.
avr_flush_cache() synchronises pending writes to EEPROM and flash with the
device. With some programmer and part combinations, flash (and sometimes
EEPROM, too) looks like a NOR memory, ie, one can only write 0 bits, not 1
bits. When this is detected, either page erase is deployed (eg, with parts
that have PDI/UPDI interfaces), or if that is not available, both EEPROM
and flash caches are fully read in, a pgm->chip_erase() command is issued
and both EEPROM and flash are written back to the device. Hence, it can
take minutes to ensure that a single previously cleared bit is set and,
therefore, this routine should be called sparingly.
avr_chip_erase_cached() erases the chip and discards pending writes() to
flash or EEPROM. It presets the flash cache to all 0xff alleviating the
need to read from the device flash. However, if the programmer serves
bootloaders (pgm->prog_modes & PM_SPM) then the flash cache is reset
instead, necessitating flash memory be fetched from the device on first
read; the reason for this is that bootloaders emulate chip erase and they
won't overwrite themselves (some bootloaders, eg, optiboot ignore chip
erase commands altogether) making it truly unknowable what the flash
contents on device is after a chip erase.
For EEPROM avr_chip_erase_cached() concludes that it has been deleted if a
previously cached EEPROM page that contained cleared bits now no longer
has these clear bits on the device. Only with this evidence is the EEPROM
cache preset to all 0xff otherwise the cache discards all pending writes
to EEPROM and is left unchanged otherwise.
Finally, avr_reset_cache() resets the cache without synchronising pending
writes() to the device.
2022-10-05 21:16:15 +00:00
|
|
|
if (werror)
|
2002-11-30 14:09:12 +00:00
|
|
|
pgm->err_led(pgm, ON);
|
2022-03-31 20:21:49 +00:00
|
|
|
|
Provide cached byte-wise read/write API (#1106)
* Provide cached byte-wise read/write API
int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char *value);
int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char data);
int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p);
int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p);
int avr_reset_cache(const PROGRAMMER *pgm, const AVRPART *p);
avr_read_byte_cached() and avr_write_byte_cached() use a cache if paged
routines are available and if the device memory is EEPROM or flash,
otherwise they fall back to pgm->read_byte() and pgm->write_byte(),
respectively. Byte-wise cached read always gets its data from the cache,
possibly after reading a page from the device memory. Byte-wise cached
write with an address in memory range only ever modifies the cache. Any
modifications are written to the device after calling avr_flush_cache() or
when attempting to read or write from a location outside the address range
of the device memory.
avr_flush_cache() synchronises pending writes to EEPROM and flash with the
device. With some programmer and part combinations, flash (and sometimes
EEPROM, too) looks like a NOR memory, ie, one can only write 0 bits, not 1
bits. When this is detected, either page erase is deployed (eg, with parts
that have PDI/UPDI interfaces), or if that is not available, both EEPROM
and flash caches are fully read in, a pgm->chip_erase() command is issued
and both EEPROM and flash are written back to the device. Hence, it can
take minutes to ensure that a single previously cleared bit is set and,
therefore, this routine should be called sparingly.
avr_chip_erase_cached() erases the chip and discards pending writes() to
flash or EEPROM. It presets the flash cache to all 0xff alleviating the
need to read from the device flash. However, if the programmer serves
bootloaders (pgm->prog_modes & PM_SPM) then the flash cache is reset
instead, necessitating flash memory be fetched from the device on first
read; the reason for this is that bootloaders emulate chip erase and they
won't overwrite themselves (some bootloaders, eg, optiboot ignore chip
erase commands altogether) making it truly unknowable what the flash
contents on device is after a chip erase.
For EEPROM avr_chip_erase_cached() concludes that it has been deleted if a
previously cached EEPROM page that contained cleared bits now no longer
has these clear bits on the device. Only with this evidence is the EEPROM
cache preset to all 0xff otherwise the cache discards all pending writes
to EEPROM and is left unchanged otherwise.
Finally, avr_reset_cache() resets the cache without synchronising pending
writes() to the device.
2022-10-05 21:16:15 +00:00
|
|
|
report_progress(i, len + data.bytes_grown, NULL);
|
2001-01-19 02:46:50 +00:00
|
|
|
}
|
2022-03-31 20:21:49 +00:00
|
|
|
report_progress(1, 1, NULL);
|
2001-01-19 02:46:50 +00:00
|
|
|
|
|
|
|
free(buf);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-10-11 13:40:37 +00:00
|
|
|
static int cmd_flush(PROGRAMMER *pgm, AVRPART *p, int ac, char *av[]) {
|
Provide cached byte-wise read/write API (#1106)
* Provide cached byte-wise read/write API
int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char *value);
int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char data);
int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p);
int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p);
int avr_reset_cache(const PROGRAMMER *pgm, const AVRPART *p);
avr_read_byte_cached() and avr_write_byte_cached() use a cache if paged
routines are available and if the device memory is EEPROM or flash,
otherwise they fall back to pgm->read_byte() and pgm->write_byte(),
respectively. Byte-wise cached read always gets its data from the cache,
possibly after reading a page from the device memory. Byte-wise cached
write with an address in memory range only ever modifies the cache. Any
modifications are written to the device after calling avr_flush_cache() or
when attempting to read or write from a location outside the address range
of the device memory.
avr_flush_cache() synchronises pending writes to EEPROM and flash with the
device. With some programmer and part combinations, flash (and sometimes
EEPROM, too) looks like a NOR memory, ie, one can only write 0 bits, not 1
bits. When this is detected, either page erase is deployed (eg, with parts
that have PDI/UPDI interfaces), or if that is not available, both EEPROM
and flash caches are fully read in, a pgm->chip_erase() command is issued
and both EEPROM and flash are written back to the device. Hence, it can
take minutes to ensure that a single previously cleared bit is set and,
therefore, this routine should be called sparingly.
avr_chip_erase_cached() erases the chip and discards pending writes() to
flash or EEPROM. It presets the flash cache to all 0xff alleviating the
need to read from the device flash. However, if the programmer serves
bootloaders (pgm->prog_modes & PM_SPM) then the flash cache is reset
instead, necessitating flash memory be fetched from the device on first
read; the reason for this is that bootloaders emulate chip erase and they
won't overwrite themselves (some bootloaders, eg, optiboot ignore chip
erase commands altogether) making it truly unknowable what the flash
contents on device is after a chip erase.
For EEPROM avr_chip_erase_cached() concludes that it has been deleted if a
previously cached EEPROM page that contained cleared bits now no longer
has these clear bits on the device. Only with this evidence is the EEPROM
cache preset to all 0xff otherwise the cache discards all pending writes
to EEPROM and is left unchanged otherwise.
Finally, avr_reset_cache() resets the cache without synchronising pending
writes() to the device.
2022-10-05 21:16:15 +00:00
|
|
|
pgm->flush_cache(pgm, p);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-10-11 13:40:37 +00:00
|
|
|
static int cmd_abort(PROGRAMMER *pgm, AVRPART *p, int ac, char *av[]) {
|
Provide cached byte-wise read/write API (#1106)
* Provide cached byte-wise read/write API
int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char *value);
int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char data);
int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p);
int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p);
int avr_reset_cache(const PROGRAMMER *pgm, const AVRPART *p);
avr_read_byte_cached() and avr_write_byte_cached() use a cache if paged
routines are available and if the device memory is EEPROM or flash,
otherwise they fall back to pgm->read_byte() and pgm->write_byte(),
respectively. Byte-wise cached read always gets its data from the cache,
possibly after reading a page from the device memory. Byte-wise cached
write with an address in memory range only ever modifies the cache. Any
modifications are written to the device after calling avr_flush_cache() or
when attempting to read or write from a location outside the address range
of the device memory.
avr_flush_cache() synchronises pending writes to EEPROM and flash with the
device. With some programmer and part combinations, flash (and sometimes
EEPROM, too) looks like a NOR memory, ie, one can only write 0 bits, not 1
bits. When this is detected, either page erase is deployed (eg, with parts
that have PDI/UPDI interfaces), or if that is not available, both EEPROM
and flash caches are fully read in, a pgm->chip_erase() command is issued
and both EEPROM and flash are written back to the device. Hence, it can
take minutes to ensure that a single previously cleared bit is set and,
therefore, this routine should be called sparingly.
avr_chip_erase_cached() erases the chip and discards pending writes() to
flash or EEPROM. It presets the flash cache to all 0xff alleviating the
need to read from the device flash. However, if the programmer serves
bootloaders (pgm->prog_modes & PM_SPM) then the flash cache is reset
instead, necessitating flash memory be fetched from the device on first
read; the reason for this is that bootloaders emulate chip erase and they
won't overwrite themselves (some bootloaders, eg, optiboot ignore chip
erase commands altogether) making it truly unknowable what the flash
contents on device is after a chip erase.
For EEPROM avr_chip_erase_cached() concludes that it has been deleted if a
previously cached EEPROM page that contained cleared bits now no longer
has these clear bits on the device. Only with this evidence is the EEPROM
cache preset to all 0xff otherwise the cache discards all pending writes
to EEPROM and is left unchanged otherwise.
Finally, avr_reset_cache() resets the cache without synchronising pending
writes() to the device.
2022-10-05 21:16:15 +00:00
|
|
|
pgm->reset_cache(pgm, p);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-10-11 13:40:37 +00:00
|
|
|
static int cmd_send(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
2001-11-19 17:44:24 +00:00
|
|
|
unsigned char cmd[4], res[4];
|
2022-10-11 13:40:37 +00:00
|
|
|
char *e;
|
2001-11-19 17:44:24 +00:00
|
|
|
int i;
|
|
|
|
int len;
|
|
|
|
|
2009-02-17 15:31:27 +00:00
|
|
|
if (spi_mode && (pgm->spi == NULL)) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%s (send): the %s programmer does not support direct SPI transfers\n",
|
2022-07-12 10:58:51 +00:00
|
|
|
progname, pgm->type);
|
2009-02-17 15:31:27 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if ((argc > 5) || ((argc < 5) && (!spi_mode))) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, spi_mode?
|
2009-02-17 15:31:27 +00:00
|
|
|
"Usage: send <byte1> [<byte2> [<byte3> [<byte4>]]]\n":
|
|
|
|
"Usage: send <byte1> <byte2> <byte3> <byte4>\n");
|
2001-11-19 17:44:24 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* number of bytes to write at the specified address */
|
|
|
|
len = argc - 1;
|
|
|
|
|
|
|
|
/* load command bytes */
|
|
|
|
for (i=1; i<argc; i++) {
|
|
|
|
cmd[i-1] = strtoul(argv[i], &e, 0);
|
|
|
|
if (*e || (e == argv[i])) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%s (send): can't parse byte %s\n",
|
2022-07-12 10:58:51 +00:00
|
|
|
progname, argv[i]);
|
2001-11-19 17:44:24 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-11-30 14:09:12 +00:00
|
|
|
pgm->err_led(pgm, OFF);
|
2001-11-19 17:44:24 +00:00
|
|
|
|
2009-02-17 15:31:27 +00:00
|
|
|
if (spi_mode)
|
|
|
|
pgm->spi(pgm, cmd, res, argc-1);
|
|
|
|
else
|
|
|
|
pgm->cmd(pgm, cmd, res);
|
2001-11-19 17:44:24 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* display results
|
|
|
|
*/
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "results:");
|
2001-11-19 17:44:24 +00:00
|
|
|
for (i=0; i<len; i++)
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, " %02x", res[i]);
|
|
|
|
terminal_message(MSG_INFO, "\n");
|
2001-11-19 17:44:24 +00:00
|
|
|
|
|
|
|
fprintf(stdout, "\n");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-10-11 13:40:37 +00:00
|
|
|
static int cmd_erase(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%s: erasing chip\n", progname);
|
Provide cached byte-wise read/write API (#1106)
* Provide cached byte-wise read/write API
int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char *value);
int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char data);
int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p);
int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p);
int avr_reset_cache(const PROGRAMMER *pgm, const AVRPART *p);
avr_read_byte_cached() and avr_write_byte_cached() use a cache if paged
routines are available and if the device memory is EEPROM or flash,
otherwise they fall back to pgm->read_byte() and pgm->write_byte(),
respectively. Byte-wise cached read always gets its data from the cache,
possibly after reading a page from the device memory. Byte-wise cached
write with an address in memory range only ever modifies the cache. Any
modifications are written to the device after calling avr_flush_cache() or
when attempting to read or write from a location outside the address range
of the device memory.
avr_flush_cache() synchronises pending writes to EEPROM and flash with the
device. With some programmer and part combinations, flash (and sometimes
EEPROM, too) looks like a NOR memory, ie, one can only write 0 bits, not 1
bits. When this is detected, either page erase is deployed (eg, with parts
that have PDI/UPDI interfaces), or if that is not available, both EEPROM
and flash caches are fully read in, a pgm->chip_erase() command is issued
and both EEPROM and flash are written back to the device. Hence, it can
take minutes to ensure that a single previously cleared bit is set and,
therefore, this routine should be called sparingly.
avr_chip_erase_cached() erases the chip and discards pending writes() to
flash or EEPROM. It presets the flash cache to all 0xff alleviating the
need to read from the device flash. However, if the programmer serves
bootloaders (pgm->prog_modes & PM_SPM) then the flash cache is reset
instead, necessitating flash memory be fetched from the device on first
read; the reason for this is that bootloaders emulate chip erase and they
won't overwrite themselves (some bootloaders, eg, optiboot ignore chip
erase commands altogether) making it truly unknowable what the flash
contents on device is after a chip erase.
For EEPROM avr_chip_erase_cached() concludes that it has been deleted if a
previously cached EEPROM page that contained cleared bits now no longer
has these clear bits on the device. Only with this evidence is the EEPROM
cache preset to all 0xff otherwise the cache discards all pending writes
to EEPROM and is left unchanged otherwise.
Finally, avr_reset_cache() resets the cache without synchronising pending
writes() to the device.
2022-10-05 21:16:15 +00:00
|
|
|
// Erase chip and clear cache
|
|
|
|
pgm->chip_erase_cached(pgm, p);
|
|
|
|
|
2001-01-19 02:46:50 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-10-11 13:40:37 +00:00
|
|
|
static int cmd_pgerase(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
|
|
|
if(argc < 3) {
|
|
|
|
terminal_message(MSG_INFO, "Usage: pgerase <memory> <addr>\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *memtype = argv[1];
|
|
|
|
AVRMEM *mem = avr_locate_mem(p, memtype);
|
|
|
|
if(!mem) {
|
|
|
|
terminal_message(MSG_INFO, "%s (pgerase): %s memory type not defined for part %s\n",
|
|
|
|
progname, memtype, p->desc);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if(!avr_has_paged_access(pgm, mem)) {
|
|
|
|
terminal_message(MSG_INFO, "%s (pgerase): %s memory cannot be paged addressed by %s\n",
|
|
|
|
progname, memtype, ldata(lfirst(pgm->id)));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int maxsize = mem->size;
|
|
|
|
|
|
|
|
char *end_ptr;
|
|
|
|
int addr = strtoul(argv[2], &end_ptr, 0);
|
|
|
|
if(*end_ptr || (end_ptr == argv[2])) {
|
|
|
|
terminal_message(MSG_INFO, "%s (pgerase): can't parse address %s\n",
|
|
|
|
progname, argv[2]);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (addr < 0 || addr >= maxsize) {
|
|
|
|
terminal_message(MSG_INFO, "%s (pgerase): %s address 0x%05x is out of range [0, 0x%05x]\n",
|
|
|
|
progname, mem->desc, addr, maxsize-1);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// terminal_message(MSG_INFO, "%s: %s page erase 0x%05x\n", progname, mem->desc, addr & ~(mem->page_size-1));
|
|
|
|
if(pgm->page_erase_cached(pgm, p, mem, (unsigned int) addr) < 0) {
|
|
|
|
terminal_message(MSG_INFO, "%s (pgerase): %s page at 0x%05x could not be erased\n",
|
|
|
|
progname, mem->desc, addr);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int cmd_part(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
2001-01-19 02:46:50 +00:00
|
|
|
fprintf(stdout, "\n");
|
2002-02-14 02:48:07 +00:00
|
|
|
avr_display(stdout, p, "", 0);
|
2001-01-19 02:46:50 +00:00
|
|
|
fprintf(stdout, "\n");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-10-11 13:40:37 +00:00
|
|
|
static int cmd_sig(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
2001-01-19 02:46:50 +00:00
|
|
|
int i;
|
2001-11-21 02:46:55 +00:00
|
|
|
int rc;
|
2022-10-11 13:40:37 +00:00
|
|
|
AVRMEM *m;
|
2001-01-19 02:46:50 +00:00
|
|
|
|
2002-11-30 14:09:12 +00:00
|
|
|
rc = avr_signature(pgm, p);
|
2001-11-21 02:46:55 +00:00
|
|
|
if (rc != 0) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%s (sig): error reading signature data, rc=%d\n",
|
2022-07-12 10:59:42 +00:00
|
|
|
progname, rc);
|
2001-11-21 02:46:55 +00:00
|
|
|
}
|
2001-11-19 17:44:24 +00:00
|
|
|
|
2001-11-21 02:46:55 +00:00
|
|
|
m = avr_locate_mem(p, "signature");
|
|
|
|
if (m == NULL) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%s (sig): signature data not defined for device %s\n",
|
2022-07-12 10:58:51 +00:00
|
|
|
progname, p->desc);
|
2001-11-21 02:46:55 +00:00
|
|
|
}
|
|
|
|
else {
|
2002-10-11 19:36:56 +00:00
|
|
|
fprintf(stdout, "Device signature = 0x");
|
2001-11-21 02:46:55 +00:00
|
|
|
for (i=0; i<m->size; i++)
|
|
|
|
fprintf(stdout, "%02x", m->buf[i]);
|
|
|
|
fprintf(stdout, "\n\n");
|
|
|
|
}
|
2001-11-19 17:44:24 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-10-11 13:40:37 +00:00
|
|
|
static int cmd_quit(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
2015-01-02 01:08:14 +00:00
|
|
|
/* FUSE bit verify will fail if left in SPI mode */
|
|
|
|
if (spi_mode) {
|
|
|
|
cmd_pgm(pgm, p, 0, NULL);
|
|
|
|
}
|
2001-01-19 02:46:50 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-10-11 13:40:37 +00:00
|
|
|
static int cmd_parms(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
2003-07-24 21:26:28 +00:00
|
|
|
pgm->print_parms(pgm);
|
2022-09-28 19:59:50 +00:00
|
|
|
terminal_message(MSG_INFO, "\n");
|
2003-07-24 21:26:28 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-10-11 13:40:37 +00:00
|
|
|
static int cmd_vtarg(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
2003-07-24 21:26:28 +00:00
|
|
|
int rc;
|
|
|
|
double v;
|
|
|
|
char *endp;
|
|
|
|
|
|
|
|
if (argc != 2) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "Usage: vtarg <value>\n");
|
2003-07-24 21:26:28 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
v = strtod(argv[1], &endp);
|
|
|
|
if (endp == argv[1]) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%s (vtarg): can't parse voltage %s\n",
|
2022-07-12 10:58:51 +00:00
|
|
|
progname, argv[1]);
|
2003-07-24 21:26:28 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if ((rc = pgm->set_vtarget(pgm, v)) != 0) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%s (vtarg): failed to set V[target] (rc = %d)\n",
|
2022-07-12 10:58:51 +00:00
|
|
|
progname, rc);
|
2003-07-24 21:26:28 +00:00
|
|
|
return -3;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-10-11 13:40:37 +00:00
|
|
|
static int cmd_fosc(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
2003-07-24 21:26:28 +00:00
|
|
|
int rc;
|
|
|
|
double v;
|
|
|
|
char *endp;
|
|
|
|
|
|
|
|
if (argc != 2) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "Usage: fosc <value>[M|k] | off\n");
|
2003-07-24 21:26:28 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
v = strtod(argv[1], &endp);
|
|
|
|
if (endp == argv[1]) {
|
|
|
|
if (strcmp(argv[1], "off") == 0)
|
|
|
|
v = 0.0;
|
|
|
|
else {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%s (fosc): can't parse frequency %s\n",
|
2022-07-12 10:58:51 +00:00
|
|
|
progname, argv[1]);
|
2003-07-24 21:26:28 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (*endp == 'm' || *endp == 'M')
|
|
|
|
v *= 1e6;
|
|
|
|
else if (*endp == 'k' || *endp == 'K')
|
|
|
|
v *= 1e3;
|
|
|
|
if ((rc = pgm->set_fosc(pgm, v)) != 0) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%s (fosc): failed to set oscillator frequency (rc = %d)\n",
|
2022-07-12 10:58:51 +00:00
|
|
|
progname, rc);
|
2003-07-24 21:26:28 +00:00
|
|
|
return -3;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-10-11 13:40:37 +00:00
|
|
|
static int cmd_sck(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
2004-07-07 08:59:07 +00:00
|
|
|
int rc;
|
|
|
|
double v;
|
|
|
|
char *endp;
|
|
|
|
|
|
|
|
if (argc != 2) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "Usage: sck <value>\n");
|
2004-07-07 08:59:07 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
v = strtod(argv[1], &endp);
|
|
|
|
if (endp == argv[1]) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%s (sck): can't parse period %s\n",
|
2022-07-12 10:58:51 +00:00
|
|
|
progname, argv[1]);
|
2004-07-07 08:59:07 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
v *= 1e-6; /* Convert from microseconds to seconds. */
|
|
|
|
if ((rc = pgm->set_sck_period(pgm, v)) != 0) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%s (sck): failed to set SCK period (rc = %d)\n",
|
2022-07-12 10:58:51 +00:00
|
|
|
progname, rc);
|
2004-07-07 08:59:07 +00:00
|
|
|
return -3;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-10-11 13:40:37 +00:00
|
|
|
static int cmd_varef(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
2003-07-24 21:26:28 +00:00
|
|
|
int rc;
|
2008-03-14 13:00:08 +00:00
|
|
|
unsigned int chan;
|
2003-07-24 21:26:28 +00:00
|
|
|
double v;
|
|
|
|
char *endp;
|
|
|
|
|
2008-03-14 13:00:08 +00:00
|
|
|
if (argc != 2 && argc != 3) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "Usage: varef [channel] <value>\n");
|
2003-07-24 21:26:28 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2008-03-14 13:00:08 +00:00
|
|
|
if (argc == 2) {
|
|
|
|
chan = 0;
|
|
|
|
v = strtod(argv[1], &endp);
|
|
|
|
if (endp == argv[1]) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%s (varef): can't parse voltage %s\n",
|
2022-07-12 10:58:51 +00:00
|
|
|
progname, argv[1]);
|
2008-03-14 13:00:08 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
chan = strtoul(argv[1], &endp, 10);
|
|
|
|
if (endp == argv[1]) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%s (varef): can't parse channel %s\n",
|
2022-07-12 10:58:51 +00:00
|
|
|
progname, argv[1]);
|
2008-03-14 13:00:08 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
v = strtod(argv[2], &endp);
|
|
|
|
if (endp == argv[2]) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%s (varef): can't parse voltage %s\n",
|
2022-07-12 10:58:51 +00:00
|
|
|
progname, argv[2]);
|
2008-03-14 13:00:08 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2003-07-24 21:26:28 +00:00
|
|
|
}
|
2008-03-14 13:00:08 +00:00
|
|
|
if ((rc = pgm->set_varef(pgm, chan, v)) != 0) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%s (varef): failed to set V[aref] (rc = %d)\n",
|
2022-07-12 10:58:51 +00:00
|
|
|
progname, rc);
|
2003-07-24 21:26:28 +00:00
|
|
|
return -3;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-10-11 13:40:37 +00:00
|
|
|
static int cmd_help(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
2001-01-19 02:46:50 +00:00
|
|
|
int i;
|
|
|
|
|
2022-07-12 10:50:23 +00:00
|
|
|
fprintf(stdout, "Valid commands:\n");
|
2001-01-19 02:46:50 +00:00
|
|
|
for (i=0; i<NCMDS; i++) {
|
2022-10-11 13:40:37 +00:00
|
|
|
if(!*(void (**)(void)) ((char *) pgm + cmd[i].fnoff))
|
|
|
|
continue;
|
2022-07-12 10:50:23 +00:00
|
|
|
fprintf(stdout, " %-7s : ", cmd[i].name);
|
2001-01-19 02:46:50 +00:00
|
|
|
fprintf(stdout, cmd[i].desc, cmd[i].name);
|
|
|
|
fprintf(stdout, "\n");
|
|
|
|
}
|
Provide cached byte-wise read/write API (#1106)
* Provide cached byte-wise read/write API
int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char *value);
int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char data);
int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p);
int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p);
int avr_reset_cache(const PROGRAMMER *pgm, const AVRPART *p);
avr_read_byte_cached() and avr_write_byte_cached() use a cache if paged
routines are available and if the device memory is EEPROM or flash,
otherwise they fall back to pgm->read_byte() and pgm->write_byte(),
respectively. Byte-wise cached read always gets its data from the cache,
possibly after reading a page from the device memory. Byte-wise cached
write with an address in memory range only ever modifies the cache. Any
modifications are written to the device after calling avr_flush_cache() or
when attempting to read or write from a location outside the address range
of the device memory.
avr_flush_cache() synchronises pending writes to EEPROM and flash with the
device. With some programmer and part combinations, flash (and sometimes
EEPROM, too) looks like a NOR memory, ie, one can only write 0 bits, not 1
bits. When this is detected, either page erase is deployed (eg, with parts
that have PDI/UPDI interfaces), or if that is not available, both EEPROM
and flash caches are fully read in, a pgm->chip_erase() command is issued
and both EEPROM and flash are written back to the device. Hence, it can
take minutes to ensure that a single previously cleared bit is set and,
therefore, this routine should be called sparingly.
avr_chip_erase_cached() erases the chip and discards pending writes() to
flash or EEPROM. It presets the flash cache to all 0xff alleviating the
need to read from the device flash. However, if the programmer serves
bootloaders (pgm->prog_modes & PM_SPM) then the flash cache is reset
instead, necessitating flash memory be fetched from the device on first
read; the reason for this is that bootloaders emulate chip erase and they
won't overwrite themselves (some bootloaders, eg, optiboot ignore chip
erase commands altogether) making it truly unknowable what the flash
contents on device is after a chip erase.
For EEPROM avr_chip_erase_cached() concludes that it has been deleted if a
previously cached EEPROM page that contained cleared bits now no longer
has these clear bits on the device. Only with this evidence is the EEPROM
cache preset to all 0xff otherwise the cache discards all pending writes
to EEPROM and is left unchanged otherwise.
Finally, avr_reset_cache() resets the cache without synchronising pending
writes() to the device.
2022-10-05 21:16:15 +00:00
|
|
|
fprintf(stdout, "\n"
|
2022-10-11 13:40:37 +00:00
|
|
|
"Note that not all programmer derivatives support all commands. Flash and\n"
|
|
|
|
"EEPROM type memories are normally read and written using a cache via paged\n"
|
|
|
|
"read and write access; the cache is synchronised on quit. Use the part\n"
|
|
|
|
"command to display valid memory types for use with dump and write.\n\n");
|
2001-01-19 02:46:50 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-10-11 13:40:37 +00:00
|
|
|
static int cmd_spi(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
|
|
|
pgm->setpin(pgm, PIN_AVR_RESET, 1);
|
|
|
|
spi_mode = 1;
|
|
|
|
return 0;
|
2009-02-17 15:31:27 +00:00
|
|
|
}
|
|
|
|
|
2022-10-11 13:40:37 +00:00
|
|
|
static int cmd_pgm(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
|
|
|
pgm->setpin(pgm, PIN_AVR_RESET, 0);
|
|
|
|
spi_mode = 0;
|
|
|
|
pgm->initialize(pgm, p);
|
|
|
|
return 0;
|
2009-02-17 15:31:27 +00:00
|
|
|
}
|
2001-01-19 02:46:50 +00:00
|
|
|
|
2022-10-11 13:40:37 +00:00
|
|
|
static int cmd_verbose(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
2013-09-08 19:31:48 +00:00
|
|
|
int nverb;
|
|
|
|
char *endp;
|
|
|
|
|
|
|
|
if (argc != 1 && argc != 2) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "Usage: verbose [<value>]\n");
|
2013-09-08 19:31:48 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (argc == 1) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "Verbosity level: %d\n", verbose);
|
2013-09-08 19:31:48 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
nverb = strtol(argv[1], &endp, 0);
|
2022-07-12 11:30:29 +00:00
|
|
|
if (endp == argv[1] || *endp) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%s (verbose): can't parse verbosity level %s\n",
|
2022-07-12 11:30:29 +00:00
|
|
|
progname, argv[1]);
|
2013-09-08 19:31:48 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (nverb < 0) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%s: verbosity level must not be negative: %d\n",
|
2022-07-12 10:58:51 +00:00
|
|
|
progname, nverb);
|
2013-09-08 19:31:48 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
verbose = nverb;
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "New verbosity level: %d\n", verbose);
|
2013-09-08 19:31:48 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-10-11 13:40:37 +00:00
|
|
|
static int cmd_quell(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
2022-07-12 12:11:10 +00:00
|
|
|
int nquell;
|
|
|
|
char *endp;
|
|
|
|
|
|
|
|
if (argc != 1 && argc != 2) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "Usage: quell [<value>]\n");
|
2022-07-12 12:11:10 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (argc == 1) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "Quell level: %d\n", quell_progress);
|
2022-07-12 12:11:10 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
nquell = strtol(argv[1], &endp, 0);
|
|
|
|
if (endp == argv[1] || *endp) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%s (quell): can't parse quell level %s\n",
|
2022-07-12 12:11:10 +00:00
|
|
|
progname, argv[1]);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (nquell < 0) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%s: quell level must not be negative: %d\n",
|
2022-07-12 12:11:10 +00:00
|
|
|
progname, nquell);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
quell_progress = nquell;
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "New quell level: %d\n", quell_progress);
|
2022-07-12 12:11:10 +00:00
|
|
|
|
|
|
|
if(quell_progress > 0)
|
|
|
|
update_progress = NULL;
|
2022-07-13 10:38:43 +00:00
|
|
|
else
|
|
|
|
terminal_setup_update_progress();
|
2022-07-12 12:11:10 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-10-11 13:49:44 +00:00
|
|
|
static int tokenize(char *s, char ***argv) {
|
2022-10-08 17:02:03 +00:00
|
|
|
int i, n, l, nargs;
|
2001-01-19 02:46:50 +00:00
|
|
|
int len, slen;
|
2022-10-11 13:40:37 +00:00
|
|
|
char *buf;
|
2001-01-19 02:46:50 +00:00
|
|
|
int bufsize;
|
2022-10-11 13:40:37 +00:00
|
|
|
char **bufv;
|
|
|
|
char *bufp;
|
|
|
|
char *q, *r;
|
|
|
|
char *nbuf;
|
|
|
|
char **av;
|
2001-01-19 02:46:50 +00:00
|
|
|
|
|
|
|
slen = strlen(s);
|
|
|
|
|
Remodel logic of the size that integer items occupy in terminal write
Integers can be hexadecimal, decimal or octal. An optional case-insensitive
suffix specifies their size: HH: 8 bit, H/S: 16 bit, L: 32 bit, LL: 64 bit
An optional U suffix makes a number unsigned. Ordinary 0x hex numbers are
always treated as unsigned. +0x or -0x hex numbers are treated as signed
unless they have a U suffix. Unsigned integers cannot be larger than 2^64-1.
If n is an unsigned integer then -n is also a valid unsigned integer as in C.
Signed integers must fall into the [-2^63, 2^63-1] range or a correspondingly
smaller range when a suffix specifies a smaller type. Out of range signed
numbers trigger a warning.
Ordinary 0x hex numbers with n hex digits (counting leading zeros) use
the smallest size of 1, 2, 4 and 8 bytes that can accommodate any n-digit hex
number. If a suffix specifies a size explicitly the corresponding number of
least significant bytes are written. Otherwise, signed and unsigned integers
alike occupy the smallest of 1, 2, 4, or 8 bytes needed to accommodate them
in their respective representation.
2022-07-12 10:32:38 +00:00
|
|
|
/*
|
2001-01-19 02:46:50 +00:00
|
|
|
* initialize allow for 20 arguments, use realloc to grow this if
|
Remodel logic of the size that integer items occupy in terminal write
Integers can be hexadecimal, decimal or octal. An optional case-insensitive
suffix specifies their size: HH: 8 bit, H/S: 16 bit, L: 32 bit, LL: 64 bit
An optional U suffix makes a number unsigned. Ordinary 0x hex numbers are
always treated as unsigned. +0x or -0x hex numbers are treated as signed
unless they have a U suffix. Unsigned integers cannot be larger than 2^64-1.
If n is an unsigned integer then -n is also a valid unsigned integer as in C.
Signed integers must fall into the [-2^63, 2^63-1] range or a correspondingly
smaller range when a suffix specifies a smaller type. Out of range signed
numbers trigger a warning.
Ordinary 0x hex numbers with n hex digits (counting leading zeros) use
the smallest size of 1, 2, 4 and 8 bytes that can accommodate any n-digit hex
number. If a suffix specifies a size explicitly the corresponding number of
least significant bytes are written. Otherwise, signed and unsigned integers
alike occupy the smallest of 1, 2, 4, or 8 bytes needed to accommodate them
in their respective representation.
2022-07-12 10:32:38 +00:00
|
|
|
* necessary
|
2001-01-19 02:46:50 +00:00
|
|
|
*/
|
|
|
|
nargs = 20;
|
|
|
|
bufsize = slen + 20;
|
|
|
|
buf = malloc(bufsize);
|
|
|
|
bufv = (char **) malloc(nargs*sizeof(char *));
|
|
|
|
for (i=0; i<nargs; i++) {
|
|
|
|
bufv[i] = NULL;
|
|
|
|
}
|
|
|
|
buf[0] = 0;
|
|
|
|
|
|
|
|
n = 0;
|
|
|
|
l = 0;
|
|
|
|
nbuf = buf;
|
|
|
|
r = s;
|
|
|
|
while (*r) {
|
|
|
|
nexttok(r, &q, &r);
|
|
|
|
strcpy(nbuf, q);
|
|
|
|
bufv[n] = nbuf;
|
|
|
|
len = strlen(q);
|
|
|
|
l += len + 1;
|
|
|
|
nbuf += len + 1;
|
|
|
|
nbuf[0] = 0;
|
|
|
|
n++;
|
|
|
|
if ((n % 20) == 0) {
|
2022-01-06 10:28:39 +00:00
|
|
|
char *buf_tmp;
|
|
|
|
char **bufv_tmp;
|
2001-01-19 02:46:50 +00:00
|
|
|
/* realloc space for another 20 args */
|
|
|
|
bufsize += 20;
|
|
|
|
nargs += 20;
|
2021-11-12 22:11:49 +00:00
|
|
|
bufp = buf;
|
2022-01-06 10:28:39 +00:00
|
|
|
buf_tmp = realloc(buf, bufsize);
|
|
|
|
if (buf_tmp == NULL) {
|
|
|
|
free(buf);
|
|
|
|
free(bufv);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
buf = buf_tmp;
|
|
|
|
bufv_tmp = realloc(bufv, nargs*sizeof(char *));
|
|
|
|
if (bufv_tmp == NULL) {
|
|
|
|
free(buf);
|
|
|
|
free(bufv);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
bufv = bufv_tmp;
|
2001-01-19 02:46:50 +00:00
|
|
|
nbuf = &buf[l];
|
2021-11-12 22:11:49 +00:00
|
|
|
/* correct bufv pointers */
|
2022-10-08 17:02:03 +00:00
|
|
|
ptrdiff_t k = buf - bufp;
|
2021-11-12 22:11:49 +00:00
|
|
|
for (i=0; i<n; i++) {
|
|
|
|
bufv[i] = bufv[i] + k;
|
|
|
|
}
|
2001-01-19 02:46:50 +00:00
|
|
|
for (i=n; i<nargs; i++)
|
|
|
|
bufv[i] = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Remodel logic of the size that integer items occupy in terminal write
Integers can be hexadecimal, decimal or octal. An optional case-insensitive
suffix specifies their size: HH: 8 bit, H/S: 16 bit, L: 32 bit, LL: 64 bit
An optional U suffix makes a number unsigned. Ordinary 0x hex numbers are
always treated as unsigned. +0x or -0x hex numbers are treated as signed
unless they have a U suffix. Unsigned integers cannot be larger than 2^64-1.
If n is an unsigned integer then -n is also a valid unsigned integer as in C.
Signed integers must fall into the [-2^63, 2^63-1] range or a correspondingly
smaller range when a suffix specifies a smaller type. Out of range signed
numbers trigger a warning.
Ordinary 0x hex numbers with n hex digits (counting leading zeros) use
the smallest size of 1, 2, 4 and 8 bytes that can accommodate any n-digit hex
number. If a suffix specifies a size explicitly the corresponding number of
least significant bytes are written. Otherwise, signed and unsigned integers
alike occupy the smallest of 1, 2, 4, or 8 bytes needed to accommodate them
in their respective representation.
2022-07-12 10:32:38 +00:00
|
|
|
/*
|
2001-01-19 02:46:50 +00:00
|
|
|
* We have parsed all the args, n == argc, bufv contains an array of
|
|
|
|
* pointers to each arg, and buf points to one memory block that
|
|
|
|
* contains all the args, back to back, seperated by a nul
|
|
|
|
* terminator. Consilidate bufv and buf into one big memory block
|
|
|
|
* so that the code that calls us, will have an easy job of freeing
|
|
|
|
* this memory.
|
|
|
|
*/
|
|
|
|
av = (char **) malloc(slen + n + (n+1)*sizeof(char *));
|
|
|
|
q = (char *)&av[n+1];
|
|
|
|
memcpy(q, buf, l);
|
|
|
|
for (i=0; i<n; i++) {
|
2022-10-08 17:02:03 +00:00
|
|
|
ptrdiff_t offset = bufv[i] - buf;
|
2001-01-19 02:46:50 +00:00
|
|
|
av[i] = q + offset;
|
|
|
|
}
|
|
|
|
av[i] = NULL;
|
|
|
|
|
|
|
|
free(buf);
|
|
|
|
free(bufv);
|
|
|
|
|
|
|
|
*argv = av;
|
|
|
|
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-10-11 13:40:37 +00:00
|
|
|
static int do_cmd(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
2001-01-19 02:46:50 +00:00
|
|
|
int i;
|
|
|
|
int hold;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
len = strlen(argv[0]);
|
|
|
|
hold = -1;
|
|
|
|
for (i=0; i<NCMDS; i++) {
|
2022-10-11 13:40:37 +00:00
|
|
|
if(!*(void (**)(void)) ((char *) pgm + cmd[i].fnoff))
|
|
|
|
continue;
|
|
|
|
if (len && strcasecmp(argv[0], cmd[i].name) == 0)
|
2002-11-30 14:09:12 +00:00
|
|
|
return cmd[i].func(pgm, p, argc, argv);
|
2022-10-11 13:40:37 +00:00
|
|
|
if (len && strncasecmp(argv[0], cmd[i].name, len)==0) {
|
2001-01-19 02:46:50 +00:00
|
|
|
if (hold != -1) {
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%s (cmd): command %s is ambiguous\n",
|
2022-07-12 10:58:51 +00:00
|
|
|
progname, argv[0]);
|
2001-01-19 02:46:50 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
hold = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hold != -1)
|
2002-11-30 14:09:12 +00:00
|
|
|
return cmd[hold].func(pgm, p, argc, argv);
|
2001-01-19 02:46:50 +00:00
|
|
|
|
2022-07-13 10:48:29 +00:00
|
|
|
terminal_message(MSG_INFO, "%s (cmd): invalid command %s\n",
|
2022-07-12 10:58:51 +00:00
|
|
|
progname, argv[0]);
|
2001-01-19 02:46:50 +00:00
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-10-11 13:40:37 +00:00
|
|
|
char *terminal_get_input(const char *prompt) {
|
2022-01-07 12:15:55 +00:00
|
|
|
#if defined(HAVE_LIBREADLINE) && !defined(WIN32)
|
2003-02-27 20:08:54 +00:00
|
|
|
char *input;
|
|
|
|
input = readline(prompt);
|
|
|
|
if ((input != NULL) && (strlen(input) >= 1))
|
|
|
|
add_history(input);
|
|
|
|
|
|
|
|
return input;
|
|
|
|
#else
|
|
|
|
char input[256];
|
|
|
|
printf("%s", prompt);
|
|
|
|
if (fgets(input, sizeof(input), stdin))
|
|
|
|
{
|
|
|
|
/* FIXME: readline strips the '\n', should this too? */
|
2004-06-24 11:05:07 +00:00
|
|
|
return strdup(input);
|
2003-02-27 20:08:54 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-10-11 13:40:37 +00:00
|
|
|
int terminal_mode(PROGRAMMER *pgm, AVRPART *p) {
|
|
|
|
char *cmdbuf;
|
|
|
|
char *q;
|
|
|
|
int rc;
|
|
|
|
int argc;
|
|
|
|
char **argv;
|
2001-01-19 02:46:50 +00:00
|
|
|
|
|
|
|
rc = 0;
|
2003-02-27 20:08:54 +00:00
|
|
|
while ((cmdbuf = terminal_get_input("avrdude> ")) != NULL) {
|
Remodel logic of the size that integer items occupy in terminal write
Integers can be hexadecimal, decimal or octal. An optional case-insensitive
suffix specifies their size: HH: 8 bit, H/S: 16 bit, L: 32 bit, LL: 64 bit
An optional U suffix makes a number unsigned. Ordinary 0x hex numbers are
always treated as unsigned. +0x or -0x hex numbers are treated as signed
unless they have a U suffix. Unsigned integers cannot be larger than 2^64-1.
If n is an unsigned integer then -n is also a valid unsigned integer as in C.
Signed integers must fall into the [-2^63, 2^63-1] range or a correspondingly
smaller range when a suffix specifies a smaller type. Out of range signed
numbers trigger a warning.
Ordinary 0x hex numbers with n hex digits (counting leading zeros) use
the smallest size of 1, 2, 4 and 8 bytes that can accommodate any n-digit hex
number. If a suffix specifies a size explicitly the corresponding number of
least significant bytes are written. Otherwise, signed and unsigned integers
alike occupy the smallest of 1, 2, 4, or 8 bytes needed to accommodate them
in their respective representation.
2022-07-12 10:32:38 +00:00
|
|
|
/*
|
2001-01-19 02:46:50 +00:00
|
|
|
* find the start of the command, skipping any white space
|
|
|
|
*/
|
|
|
|
q = cmdbuf;
|
2022-07-13 10:19:21 +00:00
|
|
|
while (*q && isspace((unsigned char) *q))
|
2001-01-19 02:46:50 +00:00
|
|
|
q++;
|
|
|
|
|
|
|
|
/* skip blank lines and comments */
|
|
|
|
if (!*q || (*q == '#'))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* tokenize command line */
|
|
|
|
argc = tokenize(q, &argv);
|
2022-01-06 10:28:39 +00:00
|
|
|
if (argc < 0) {
|
|
|
|
free(cmdbuf);
|
|
|
|
return argc;
|
|
|
|
}
|
2001-01-19 02:46:50 +00:00
|
|
|
|
2022-07-14 17:31:44 +00:00
|
|
|
#if !defined(HAVE_LIBREADLINE) || defined(WIN32) || defined(__APPLE__)
|
2001-01-19 02:46:50 +00:00
|
|
|
fprintf(stdout, ">>> ");
|
2022-07-12 10:51:04 +00:00
|
|
|
for (int i=0; i<argc; i++)
|
2001-01-19 02:46:50 +00:00
|
|
|
fprintf(stdout, "%s ", argv[i]);
|
|
|
|
fprintf(stdout, "\n");
|
2022-07-12 10:51:04 +00:00
|
|
|
#endif
|
2001-01-19 02:46:50 +00:00
|
|
|
|
|
|
|
/* run the command */
|
2002-11-30 14:09:12 +00:00
|
|
|
rc = do_cmd(pgm, p, argc, argv);
|
2001-01-19 02:46:50 +00:00
|
|
|
free(argv);
|
|
|
|
if (rc > 0) {
|
|
|
|
rc = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
free(cmdbuf);
|
|
|
|
}
|
|
|
|
|
Provide cached byte-wise read/write API (#1106)
* Provide cached byte-wise read/write API
int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char *value);
int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char data);
int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p);
int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p);
int avr_reset_cache(const PROGRAMMER *pgm, const AVRPART *p);
avr_read_byte_cached() and avr_write_byte_cached() use a cache if paged
routines are available and if the device memory is EEPROM or flash,
otherwise they fall back to pgm->read_byte() and pgm->write_byte(),
respectively. Byte-wise cached read always gets its data from the cache,
possibly after reading a page from the device memory. Byte-wise cached
write with an address in memory range only ever modifies the cache. Any
modifications are written to the device after calling avr_flush_cache() or
when attempting to read or write from a location outside the address range
of the device memory.
avr_flush_cache() synchronises pending writes to EEPROM and flash with the
device. With some programmer and part combinations, flash (and sometimes
EEPROM, too) looks like a NOR memory, ie, one can only write 0 bits, not 1
bits. When this is detected, either page erase is deployed (eg, with parts
that have PDI/UPDI interfaces), or if that is not available, both EEPROM
and flash caches are fully read in, a pgm->chip_erase() command is issued
and both EEPROM and flash are written back to the device. Hence, it can
take minutes to ensure that a single previously cleared bit is set and,
therefore, this routine should be called sparingly.
avr_chip_erase_cached() erases the chip and discards pending writes() to
flash or EEPROM. It presets the flash cache to all 0xff alleviating the
need to read from the device flash. However, if the programmer serves
bootloaders (pgm->prog_modes & PM_SPM) then the flash cache is reset
instead, necessitating flash memory be fetched from the device on first
read; the reason for this is that bootloaders emulate chip erase and they
won't overwrite themselves (some bootloaders, eg, optiboot ignore chip
erase commands altogether) making it truly unknowable what the flash
contents on device is after a chip erase.
For EEPROM avr_chip_erase_cached() concludes that it has been deleted if a
previously cached EEPROM page that contained cleared bits now no longer
has these clear bits on the device. Only with this evidence is the EEPROM
cache preset to all 0xff otherwise the cache discards all pending writes
to EEPROM and is left unchanged otherwise.
Finally, avr_reset_cache() resets the cache without synchronising pending
writes() to the device.
2022-10-05 21:16:15 +00:00
|
|
|
pgm->flush_cache(pgm, p);
|
|
|
|
|
2001-01-19 02:46:50 +00:00
|
|
|
return rc;
|
|
|
|
}
|
2022-07-13 10:38:43 +00:00
|
|
|
|
|
|
|
|
2022-07-13 10:48:29 +00:00
|
|
|
int terminal_message(const int msglvl, const char *format, ...) {
|
|
|
|
int rc = 0;
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
fflush(stdout); fflush(stderr);
|
|
|
|
if (verbose >= msglvl) {
|
|
|
|
va_start(ap, format);
|
|
|
|
rc = vfprintf(stderr, format, ap);
|
|
|
|
va_end(ap);
|
|
|
|
}
|
|
|
|
fflush(stderr);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
Provide cached byte-wise read/write API (#1106)
* Provide cached byte-wise read/write API
int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char *value);
int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char data);
int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p);
int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p);
int avr_reset_cache(const PROGRAMMER *pgm, const AVRPART *p);
avr_read_byte_cached() and avr_write_byte_cached() use a cache if paged
routines are available and if the device memory is EEPROM or flash,
otherwise they fall back to pgm->read_byte() and pgm->write_byte(),
respectively. Byte-wise cached read always gets its data from the cache,
possibly after reading a page from the device memory. Byte-wise cached
write with an address in memory range only ever modifies the cache. Any
modifications are written to the device after calling avr_flush_cache() or
when attempting to read or write from a location outside the address range
of the device memory.
avr_flush_cache() synchronises pending writes to EEPROM and flash with the
device. With some programmer and part combinations, flash (and sometimes
EEPROM, too) looks like a NOR memory, ie, one can only write 0 bits, not 1
bits. When this is detected, either page erase is deployed (eg, with parts
that have PDI/UPDI interfaces), or if that is not available, both EEPROM
and flash caches are fully read in, a pgm->chip_erase() command is issued
and both EEPROM and flash are written back to the device. Hence, it can
take minutes to ensure that a single previously cleared bit is set and,
therefore, this routine should be called sparingly.
avr_chip_erase_cached() erases the chip and discards pending writes() to
flash or EEPROM. It presets the flash cache to all 0xff alleviating the
need to read from the device flash. However, if the programmer serves
bootloaders (pgm->prog_modes & PM_SPM) then the flash cache is reset
instead, necessitating flash memory be fetched from the device on first
read; the reason for this is that bootloaders emulate chip erase and they
won't overwrite themselves (some bootloaders, eg, optiboot ignore chip
erase commands altogether) making it truly unknowable what the flash
contents on device is after a chip erase.
For EEPROM avr_chip_erase_cached() concludes that it has been deleted if a
previously cached EEPROM page that contained cleared bits now no longer
has these clear bits on the device. Only with this evidence is the EEPROM
cache preset to all 0xff otherwise the cache discards all pending writes
to EEPROM and is left unchanged otherwise.
Finally, avr_reset_cache() resets the cache without synchronising pending
writes() to the device.
2022-10-05 21:16:15 +00:00
|
|
|
static void update_progress_tty(int percent, double etime, const char *hdr, int finish) {
|
2022-07-13 10:38:43 +00:00
|
|
|
static char *header;
|
Provide cached byte-wise read/write API (#1106)
* Provide cached byte-wise read/write API
int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char *value);
int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char data);
int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p);
int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p);
int avr_reset_cache(const PROGRAMMER *pgm, const AVRPART *p);
avr_read_byte_cached() and avr_write_byte_cached() use a cache if paged
routines are available and if the device memory is EEPROM or flash,
otherwise they fall back to pgm->read_byte() and pgm->write_byte(),
respectively. Byte-wise cached read always gets its data from the cache,
possibly after reading a page from the device memory. Byte-wise cached
write with an address in memory range only ever modifies the cache. Any
modifications are written to the device after calling avr_flush_cache() or
when attempting to read or write from a location outside the address range
of the device memory.
avr_flush_cache() synchronises pending writes to EEPROM and flash with the
device. With some programmer and part combinations, flash (and sometimes
EEPROM, too) looks like a NOR memory, ie, one can only write 0 bits, not 1
bits. When this is detected, either page erase is deployed (eg, with parts
that have PDI/UPDI interfaces), or if that is not available, both EEPROM
and flash caches are fully read in, a pgm->chip_erase() command is issued
and both EEPROM and flash are written back to the device. Hence, it can
take minutes to ensure that a single previously cleared bit is set and,
therefore, this routine should be called sparingly.
avr_chip_erase_cached() erases the chip and discards pending writes() to
flash or EEPROM. It presets the flash cache to all 0xff alleviating the
need to read from the device flash. However, if the programmer serves
bootloaders (pgm->prog_modes & PM_SPM) then the flash cache is reset
instead, necessitating flash memory be fetched from the device on first
read; the reason for this is that bootloaders emulate chip erase and they
won't overwrite themselves (some bootloaders, eg, optiboot ignore chip
erase commands altogether) making it truly unknowable what the flash
contents on device is after a chip erase.
For EEPROM avr_chip_erase_cached() concludes that it has been deleted if a
previously cached EEPROM page that contained cleared bits now no longer
has these clear bits on the device. Only with this evidence is the EEPROM
cache preset to all 0xff otherwise the cache discards all pending writes
to EEPROM and is left unchanged otherwise.
Finally, avr_reset_cache() resets the cache without synchronising pending
writes() to the device.
2022-10-05 21:16:15 +00:00
|
|
|
static int last, done;
|
2022-07-13 10:38:43 +00:00
|
|
|
int i;
|
|
|
|
|
Provide cached byte-wise read/write API (#1106)
* Provide cached byte-wise read/write API
int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char *value);
int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char data);
int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p);
int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p);
int avr_reset_cache(const PROGRAMMER *pgm, const AVRPART *p);
avr_read_byte_cached() and avr_write_byte_cached() use a cache if paged
routines are available and if the device memory is EEPROM or flash,
otherwise they fall back to pgm->read_byte() and pgm->write_byte(),
respectively. Byte-wise cached read always gets its data from the cache,
possibly after reading a page from the device memory. Byte-wise cached
write with an address in memory range only ever modifies the cache. Any
modifications are written to the device after calling avr_flush_cache() or
when attempting to read or write from a location outside the address range
of the device memory.
avr_flush_cache() synchronises pending writes to EEPROM and flash with the
device. With some programmer and part combinations, flash (and sometimes
EEPROM, too) looks like a NOR memory, ie, one can only write 0 bits, not 1
bits. When this is detected, either page erase is deployed (eg, with parts
that have PDI/UPDI interfaces), or if that is not available, both EEPROM
and flash caches are fully read in, a pgm->chip_erase() command is issued
and both EEPROM and flash are written back to the device. Hence, it can
take minutes to ensure that a single previously cleared bit is set and,
therefore, this routine should be called sparingly.
avr_chip_erase_cached() erases the chip and discards pending writes() to
flash or EEPROM. It presets the flash cache to all 0xff alleviating the
need to read from the device flash. However, if the programmer serves
bootloaders (pgm->prog_modes & PM_SPM) then the flash cache is reset
instead, necessitating flash memory be fetched from the device on first
read; the reason for this is that bootloaders emulate chip erase and they
won't overwrite themselves (some bootloaders, eg, optiboot ignore chip
erase commands altogether) making it truly unknowable what the flash
contents on device is after a chip erase.
For EEPROM avr_chip_erase_cached() concludes that it has been deleted if a
previously cached EEPROM page that contained cleared bits now no longer
has these clear bits on the device. Only with this evidence is the EEPROM
cache preset to all 0xff otherwise the cache discards all pending writes
to EEPROM and is left unchanged otherwise.
Finally, avr_reset_cache() resets the cache without synchronising pending
writes() to the device.
2022-10-05 21:16:15 +00:00
|
|
|
setvbuf(stderr, (char *) NULL, _IONBF, 0);
|
2022-07-13 10:38:43 +00:00
|
|
|
|
Provide cached byte-wise read/write API (#1106)
* Provide cached byte-wise read/write API
int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char *value);
int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char data);
int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p);
int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p);
int avr_reset_cache(const PROGRAMMER *pgm, const AVRPART *p);
avr_read_byte_cached() and avr_write_byte_cached() use a cache if paged
routines are available and if the device memory is EEPROM or flash,
otherwise they fall back to pgm->read_byte() and pgm->write_byte(),
respectively. Byte-wise cached read always gets its data from the cache,
possibly after reading a page from the device memory. Byte-wise cached
write with an address in memory range only ever modifies the cache. Any
modifications are written to the device after calling avr_flush_cache() or
when attempting to read or write from a location outside the address range
of the device memory.
avr_flush_cache() synchronises pending writes to EEPROM and flash with the
device. With some programmer and part combinations, flash (and sometimes
EEPROM, too) looks like a NOR memory, ie, one can only write 0 bits, not 1
bits. When this is detected, either page erase is deployed (eg, with parts
that have PDI/UPDI interfaces), or if that is not available, both EEPROM
and flash caches are fully read in, a pgm->chip_erase() command is issued
and both EEPROM and flash are written back to the device. Hence, it can
take minutes to ensure that a single previously cleared bit is set and,
therefore, this routine should be called sparingly.
avr_chip_erase_cached() erases the chip and discards pending writes() to
flash or EEPROM. It presets the flash cache to all 0xff alleviating the
need to read from the device flash. However, if the programmer serves
bootloaders (pgm->prog_modes & PM_SPM) then the flash cache is reset
instead, necessitating flash memory be fetched from the device on first
read; the reason for this is that bootloaders emulate chip erase and they
won't overwrite themselves (some bootloaders, eg, optiboot ignore chip
erase commands altogether) making it truly unknowable what the flash
contents on device is after a chip erase.
For EEPROM avr_chip_erase_cached() concludes that it has been deleted if a
previously cached EEPROM page that contained cleared bits now no longer
has these clear bits on the device. Only with this evidence is the EEPROM
cache preset to all 0xff otherwise the cache discards all pending writes
to EEPROM and is left unchanged otherwise.
Finally, avr_reset_cache() resets the cache without synchronising pending
writes() to the device.
2022-10-05 21:16:15 +00:00
|
|
|
if(hdr) {
|
2022-07-13 10:38:43 +00:00
|
|
|
avrdude_message(MSG_INFO, "\n");
|
Provide cached byte-wise read/write API (#1106)
* Provide cached byte-wise read/write API
int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char *value);
int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char data);
int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p);
int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p);
int avr_reset_cache(const PROGRAMMER *pgm, const AVRPART *p);
avr_read_byte_cached() and avr_write_byte_cached() use a cache if paged
routines are available and if the device memory is EEPROM or flash,
otherwise they fall back to pgm->read_byte() and pgm->write_byte(),
respectively. Byte-wise cached read always gets its data from the cache,
possibly after reading a page from the device memory. Byte-wise cached
write with an address in memory range only ever modifies the cache. Any
modifications are written to the device after calling avr_flush_cache() or
when attempting to read or write from a location outside the address range
of the device memory.
avr_flush_cache() synchronises pending writes to EEPROM and flash with the
device. With some programmer and part combinations, flash (and sometimes
EEPROM, too) looks like a NOR memory, ie, one can only write 0 bits, not 1
bits. When this is detected, either page erase is deployed (eg, with parts
that have PDI/UPDI interfaces), or if that is not available, both EEPROM
and flash caches are fully read in, a pgm->chip_erase() command is issued
and both EEPROM and flash are written back to the device. Hence, it can
take minutes to ensure that a single previously cleared bit is set and,
therefore, this routine should be called sparingly.
avr_chip_erase_cached() erases the chip and discards pending writes() to
flash or EEPROM. It presets the flash cache to all 0xff alleviating the
need to read from the device flash. However, if the programmer serves
bootloaders (pgm->prog_modes & PM_SPM) then the flash cache is reset
instead, necessitating flash memory be fetched from the device on first
read; the reason for this is that bootloaders emulate chip erase and they
won't overwrite themselves (some bootloaders, eg, optiboot ignore chip
erase commands altogether) making it truly unknowable what the flash
contents on device is after a chip erase.
For EEPROM avr_chip_erase_cached() concludes that it has been deleted if a
previously cached EEPROM page that contained cleared bits now no longer
has these clear bits on the device. Only with this evidence is the EEPROM
cache preset to all 0xff otherwise the cache discards all pending writes
to EEPROM and is left unchanged otherwise.
Finally, avr_reset_cache() resets the cache without synchronising pending
writes() to the device.
2022-10-05 21:16:15 +00:00
|
|
|
last = done = 0;
|
|
|
|
if(header)
|
|
|
|
free(header);
|
|
|
|
header = cfg_strdup("update_progress_tty()", hdr);
|
2022-07-13 10:38:43 +00:00
|
|
|
}
|
|
|
|
|
Provide cached byte-wise read/write API (#1106)
* Provide cached byte-wise read/write API
int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char *value);
int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char data);
int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p);
int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p);
int avr_reset_cache(const PROGRAMMER *pgm, const AVRPART *p);
avr_read_byte_cached() and avr_write_byte_cached() use a cache if paged
routines are available and if the device memory is EEPROM or flash,
otherwise they fall back to pgm->read_byte() and pgm->write_byte(),
respectively. Byte-wise cached read always gets its data from the cache,
possibly after reading a page from the device memory. Byte-wise cached
write with an address in memory range only ever modifies the cache. Any
modifications are written to the device after calling avr_flush_cache() or
when attempting to read or write from a location outside the address range
of the device memory.
avr_flush_cache() synchronises pending writes to EEPROM and flash with the
device. With some programmer and part combinations, flash (and sometimes
EEPROM, too) looks like a NOR memory, ie, one can only write 0 bits, not 1
bits. When this is detected, either page erase is deployed (eg, with parts
that have PDI/UPDI interfaces), or if that is not available, both EEPROM
and flash caches are fully read in, a pgm->chip_erase() command is issued
and both EEPROM and flash are written back to the device. Hence, it can
take minutes to ensure that a single previously cleared bit is set and,
therefore, this routine should be called sparingly.
avr_chip_erase_cached() erases the chip and discards pending writes() to
flash or EEPROM. It presets the flash cache to all 0xff alleviating the
need to read from the device flash. However, if the programmer serves
bootloaders (pgm->prog_modes & PM_SPM) then the flash cache is reset
instead, necessitating flash memory be fetched from the device on first
read; the reason for this is that bootloaders emulate chip erase and they
won't overwrite themselves (some bootloaders, eg, optiboot ignore chip
erase commands altogether) making it truly unknowable what the flash
contents on device is after a chip erase.
For EEPROM avr_chip_erase_cached() concludes that it has been deleted if a
previously cached EEPROM page that contained cleared bits now no longer
has these clear bits on the device. Only with this evidence is the EEPROM
cache preset to all 0xff otherwise the cache discards all pending writes
to EEPROM and is left unchanged otherwise.
Finally, avr_reset_cache() resets the cache without synchronising pending
writes() to the device.
2022-10-05 21:16:15 +00:00
|
|
|
percent = percent > 100? 100: percent < 0? 0: percent;
|
|
|
|
|
|
|
|
if(!done) {
|
|
|
|
if(!header)
|
|
|
|
header = cfg_strdup("update_progress_tty()", "report");
|
2022-07-13 10:38:43 +00:00
|
|
|
|
Provide cached byte-wise read/write API (#1106)
* Provide cached byte-wise read/write API
int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char *value);
int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char data);
int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p);
int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p);
int avr_reset_cache(const PROGRAMMER *pgm, const AVRPART *p);
avr_read_byte_cached() and avr_write_byte_cached() use a cache if paged
routines are available and if the device memory is EEPROM or flash,
otherwise they fall back to pgm->read_byte() and pgm->write_byte(),
respectively. Byte-wise cached read always gets its data from the cache,
possibly after reading a page from the device memory. Byte-wise cached
write with an address in memory range only ever modifies the cache. Any
modifications are written to the device after calling avr_flush_cache() or
when attempting to read or write from a location outside the address range
of the device memory.
avr_flush_cache() synchronises pending writes to EEPROM and flash with the
device. With some programmer and part combinations, flash (and sometimes
EEPROM, too) looks like a NOR memory, ie, one can only write 0 bits, not 1
bits. When this is detected, either page erase is deployed (eg, with parts
that have PDI/UPDI interfaces), or if that is not available, both EEPROM
and flash caches are fully read in, a pgm->chip_erase() command is issued
and both EEPROM and flash are written back to the device. Hence, it can
take minutes to ensure that a single previously cleared bit is set and,
therefore, this routine should be called sparingly.
avr_chip_erase_cached() erases the chip and discards pending writes() to
flash or EEPROM. It presets the flash cache to all 0xff alleviating the
need to read from the device flash. However, if the programmer serves
bootloaders (pgm->prog_modes & PM_SPM) then the flash cache is reset
instead, necessitating flash memory be fetched from the device on first
read; the reason for this is that bootloaders emulate chip erase and they
won't overwrite themselves (some bootloaders, eg, optiboot ignore chip
erase commands altogether) making it truly unknowable what the flash
contents on device is after a chip erase.
For EEPROM avr_chip_erase_cached() concludes that it has been deleted if a
previously cached EEPROM page that contained cleared bits now no longer
has these clear bits on the device. Only with this evidence is the EEPROM
cache preset to all 0xff otherwise the cache discards all pending writes
to EEPROM and is left unchanged otherwise.
Finally, avr_reset_cache() resets the cache without synchronising pending
writes() to the device.
2022-10-05 21:16:15 +00:00
|
|
|
int showperc = finish >= 0? percent: last;
|
|
|
|
|
|
|
|
char hashes[51];
|
|
|
|
memset(hashes, finish >= 0? ' ': '-', 50);
|
|
|
|
for(i=0; i<showperc; i+=2)
|
|
|
|
hashes[i/2] = '#';
|
|
|
|
hashes[50] = 0;
|
|
|
|
|
|
|
|
avrdude_message(MSG_INFO, "\r%s | %s | %d%% %0.2fs",
|
|
|
|
header, hashes, showperc, etime);
|
|
|
|
if(percent == 100) {
|
|
|
|
if(finish)
|
|
|
|
avrdude_message(MSG_INFO, "\n\n");
|
|
|
|
done = 1;
|
|
|
|
}
|
2022-07-13 10:38:43 +00:00
|
|
|
}
|
Provide cached byte-wise read/write API (#1106)
* Provide cached byte-wise read/write API
int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char *value);
int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char data);
int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p);
int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p);
int avr_reset_cache(const PROGRAMMER *pgm, const AVRPART *p);
avr_read_byte_cached() and avr_write_byte_cached() use a cache if paged
routines are available and if the device memory is EEPROM or flash,
otherwise they fall back to pgm->read_byte() and pgm->write_byte(),
respectively. Byte-wise cached read always gets its data from the cache,
possibly after reading a page from the device memory. Byte-wise cached
write with an address in memory range only ever modifies the cache. Any
modifications are written to the device after calling avr_flush_cache() or
when attempting to read or write from a location outside the address range
of the device memory.
avr_flush_cache() synchronises pending writes to EEPROM and flash with the
device. With some programmer and part combinations, flash (and sometimes
EEPROM, too) looks like a NOR memory, ie, one can only write 0 bits, not 1
bits. When this is detected, either page erase is deployed (eg, with parts
that have PDI/UPDI interfaces), or if that is not available, both EEPROM
and flash caches are fully read in, a pgm->chip_erase() command is issued
and both EEPROM and flash are written back to the device. Hence, it can
take minutes to ensure that a single previously cleared bit is set and,
therefore, this routine should be called sparingly.
avr_chip_erase_cached() erases the chip and discards pending writes() to
flash or EEPROM. It presets the flash cache to all 0xff alleviating the
need to read from the device flash. However, if the programmer serves
bootloaders (pgm->prog_modes & PM_SPM) then the flash cache is reset
instead, necessitating flash memory be fetched from the device on first
read; the reason for this is that bootloaders emulate chip erase and they
won't overwrite themselves (some bootloaders, eg, optiboot ignore chip
erase commands altogether) making it truly unknowable what the flash
contents on device is after a chip erase.
For EEPROM avr_chip_erase_cached() concludes that it has been deleted if a
previously cached EEPROM page that contained cleared bits now no longer
has these clear bits on the device. Only with this evidence is the EEPROM
cache preset to all 0xff otherwise the cache discards all pending writes
to EEPROM and is left unchanged otherwise.
Finally, avr_reset_cache() resets the cache without synchronising pending
writes() to the device.
2022-10-05 21:16:15 +00:00
|
|
|
last = percent;
|
2022-07-13 10:38:43 +00:00
|
|
|
|
Provide cached byte-wise read/write API (#1106)
* Provide cached byte-wise read/write API
int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char *value);
int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char data);
int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p);
int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p);
int avr_reset_cache(const PROGRAMMER *pgm, const AVRPART *p);
avr_read_byte_cached() and avr_write_byte_cached() use a cache if paged
routines are available and if the device memory is EEPROM or flash,
otherwise they fall back to pgm->read_byte() and pgm->write_byte(),
respectively. Byte-wise cached read always gets its data from the cache,
possibly after reading a page from the device memory. Byte-wise cached
write with an address in memory range only ever modifies the cache. Any
modifications are written to the device after calling avr_flush_cache() or
when attempting to read or write from a location outside the address range
of the device memory.
avr_flush_cache() synchronises pending writes to EEPROM and flash with the
device. With some programmer and part combinations, flash (and sometimes
EEPROM, too) looks like a NOR memory, ie, one can only write 0 bits, not 1
bits. When this is detected, either page erase is deployed (eg, with parts
that have PDI/UPDI interfaces), or if that is not available, both EEPROM
and flash caches are fully read in, a pgm->chip_erase() command is issued
and both EEPROM and flash are written back to the device. Hence, it can
take minutes to ensure that a single previously cleared bit is set and,
therefore, this routine should be called sparingly.
avr_chip_erase_cached() erases the chip and discards pending writes() to
flash or EEPROM. It presets the flash cache to all 0xff alleviating the
need to read from the device flash. However, if the programmer serves
bootloaders (pgm->prog_modes & PM_SPM) then the flash cache is reset
instead, necessitating flash memory be fetched from the device on first
read; the reason for this is that bootloaders emulate chip erase and they
won't overwrite themselves (some bootloaders, eg, optiboot ignore chip
erase commands altogether) making it truly unknowable what the flash
contents on device is after a chip erase.
For EEPROM avr_chip_erase_cached() concludes that it has been deleted if a
previously cached EEPROM page that contained cleared bits now no longer
has these clear bits on the device. Only with this evidence is the EEPROM
cache preset to all 0xff otherwise the cache discards all pending writes
to EEPROM and is left unchanged otherwise.
Finally, avr_reset_cache() resets the cache without synchronising pending
writes() to the device.
2022-10-05 21:16:15 +00:00
|
|
|
setvbuf(stderr, (char *) NULL, _IOLBF, 0);
|
2022-07-13 10:38:43 +00:00
|
|
|
}
|
|
|
|
|
Provide cached byte-wise read/write API (#1106)
* Provide cached byte-wise read/write API
int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char *value);
int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char data);
int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p);
int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p);
int avr_reset_cache(const PROGRAMMER *pgm, const AVRPART *p);
avr_read_byte_cached() and avr_write_byte_cached() use a cache if paged
routines are available and if the device memory is EEPROM or flash,
otherwise they fall back to pgm->read_byte() and pgm->write_byte(),
respectively. Byte-wise cached read always gets its data from the cache,
possibly after reading a page from the device memory. Byte-wise cached
write with an address in memory range only ever modifies the cache. Any
modifications are written to the device after calling avr_flush_cache() or
when attempting to read or write from a location outside the address range
of the device memory.
avr_flush_cache() synchronises pending writes to EEPROM and flash with the
device. With some programmer and part combinations, flash (and sometimes
EEPROM, too) looks like a NOR memory, ie, one can only write 0 bits, not 1
bits. When this is detected, either page erase is deployed (eg, with parts
that have PDI/UPDI interfaces), or if that is not available, both EEPROM
and flash caches are fully read in, a pgm->chip_erase() command is issued
and both EEPROM and flash are written back to the device. Hence, it can
take minutes to ensure that a single previously cleared bit is set and,
therefore, this routine should be called sparingly.
avr_chip_erase_cached() erases the chip and discards pending writes() to
flash or EEPROM. It presets the flash cache to all 0xff alleviating the
need to read from the device flash. However, if the programmer serves
bootloaders (pgm->prog_modes & PM_SPM) then the flash cache is reset
instead, necessitating flash memory be fetched from the device on first
read; the reason for this is that bootloaders emulate chip erase and they
won't overwrite themselves (some bootloaders, eg, optiboot ignore chip
erase commands altogether) making it truly unknowable what the flash
contents on device is after a chip erase.
For EEPROM avr_chip_erase_cached() concludes that it has been deleted if a
previously cached EEPROM page that contained cleared bits now no longer
has these clear bits on the device. Only with this evidence is the EEPROM
cache preset to all 0xff otherwise the cache discards all pending writes
to EEPROM and is left unchanged otherwise.
Finally, avr_reset_cache() resets the cache without synchronising pending
writes() to the device.
2022-10-05 21:16:15 +00:00
|
|
|
static void update_progress_no_tty(int percent, double etime, const char *hdr, int finish) {
|
|
|
|
static int last, done;
|
|
|
|
|
|
|
|
setvbuf(stderr, (char *) NULL, _IONBF, 0);
|
2022-07-13 10:38:43 +00:00
|
|
|
|
Provide cached byte-wise read/write API (#1106)
* Provide cached byte-wise read/write API
int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char *value);
int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char data);
int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p);
int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p);
int avr_reset_cache(const PROGRAMMER *pgm, const AVRPART *p);
avr_read_byte_cached() and avr_write_byte_cached() use a cache if paged
routines are available and if the device memory is EEPROM or flash,
otherwise they fall back to pgm->read_byte() and pgm->write_byte(),
respectively. Byte-wise cached read always gets its data from the cache,
possibly after reading a page from the device memory. Byte-wise cached
write with an address in memory range only ever modifies the cache. Any
modifications are written to the device after calling avr_flush_cache() or
when attempting to read or write from a location outside the address range
of the device memory.
avr_flush_cache() synchronises pending writes to EEPROM and flash with the
device. With some programmer and part combinations, flash (and sometimes
EEPROM, too) looks like a NOR memory, ie, one can only write 0 bits, not 1
bits. When this is detected, either page erase is deployed (eg, with parts
that have PDI/UPDI interfaces), or if that is not available, both EEPROM
and flash caches are fully read in, a pgm->chip_erase() command is issued
and both EEPROM and flash are written back to the device. Hence, it can
take minutes to ensure that a single previously cleared bit is set and,
therefore, this routine should be called sparingly.
avr_chip_erase_cached() erases the chip and discards pending writes() to
flash or EEPROM. It presets the flash cache to all 0xff alleviating the
need to read from the device flash. However, if the programmer serves
bootloaders (pgm->prog_modes & PM_SPM) then the flash cache is reset
instead, necessitating flash memory be fetched from the device on first
read; the reason for this is that bootloaders emulate chip erase and they
won't overwrite themselves (some bootloaders, eg, optiboot ignore chip
erase commands altogether) making it truly unknowable what the flash
contents on device is after a chip erase.
For EEPROM avr_chip_erase_cached() concludes that it has been deleted if a
previously cached EEPROM page that contained cleared bits now no longer
has these clear bits on the device. Only with this evidence is the EEPROM
cache preset to all 0xff otherwise the cache discards all pending writes
to EEPROM and is left unchanged otherwise.
Finally, avr_reset_cache() resets the cache without synchronising pending
writes() to the device.
2022-10-05 21:16:15 +00:00
|
|
|
percent = percent > 100? 100: percent < 0? 0: percent;
|
2022-07-13 10:38:43 +00:00
|
|
|
|
Provide cached byte-wise read/write API (#1106)
* Provide cached byte-wise read/write API
int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char *value);
int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char data);
int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p);
int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p);
int avr_reset_cache(const PROGRAMMER *pgm, const AVRPART *p);
avr_read_byte_cached() and avr_write_byte_cached() use a cache if paged
routines are available and if the device memory is EEPROM or flash,
otherwise they fall back to pgm->read_byte() and pgm->write_byte(),
respectively. Byte-wise cached read always gets its data from the cache,
possibly after reading a page from the device memory. Byte-wise cached
write with an address in memory range only ever modifies the cache. Any
modifications are written to the device after calling avr_flush_cache() or
when attempting to read or write from a location outside the address range
of the device memory.
avr_flush_cache() synchronises pending writes to EEPROM and flash with the
device. With some programmer and part combinations, flash (and sometimes
EEPROM, too) looks like a NOR memory, ie, one can only write 0 bits, not 1
bits. When this is detected, either page erase is deployed (eg, with parts
that have PDI/UPDI interfaces), or if that is not available, both EEPROM
and flash caches are fully read in, a pgm->chip_erase() command is issued
and both EEPROM and flash are written back to the device. Hence, it can
take minutes to ensure that a single previously cleared bit is set and,
therefore, this routine should be called sparingly.
avr_chip_erase_cached() erases the chip and discards pending writes() to
flash or EEPROM. It presets the flash cache to all 0xff alleviating the
need to read from the device flash. However, if the programmer serves
bootloaders (pgm->prog_modes & PM_SPM) then the flash cache is reset
instead, necessitating flash memory be fetched from the device on first
read; the reason for this is that bootloaders emulate chip erase and they
won't overwrite themselves (some bootloaders, eg, optiboot ignore chip
erase commands altogether) making it truly unknowable what the flash
contents on device is after a chip erase.
For EEPROM avr_chip_erase_cached() concludes that it has been deleted if a
previously cached EEPROM page that contained cleared bits now no longer
has these clear bits on the device. Only with this evidence is the EEPROM
cache preset to all 0xff otherwise the cache discards all pending writes
to EEPROM and is left unchanged otherwise.
Finally, avr_reset_cache() resets the cache without synchronising pending
writes() to the device.
2022-10-05 21:16:15 +00:00
|
|
|
if(hdr) {
|
2022-07-13 10:38:43 +00:00
|
|
|
avrdude_message(MSG_INFO, "\n%s | ", hdr);
|
Provide cached byte-wise read/write API (#1106)
* Provide cached byte-wise read/write API
int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char *value);
int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char data);
int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p);
int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p);
int avr_reset_cache(const PROGRAMMER *pgm, const AVRPART *p);
avr_read_byte_cached() and avr_write_byte_cached() use a cache if paged
routines are available and if the device memory is EEPROM or flash,
otherwise they fall back to pgm->read_byte() and pgm->write_byte(),
respectively. Byte-wise cached read always gets its data from the cache,
possibly after reading a page from the device memory. Byte-wise cached
write with an address in memory range only ever modifies the cache. Any
modifications are written to the device after calling avr_flush_cache() or
when attempting to read or write from a location outside the address range
of the device memory.
avr_flush_cache() synchronises pending writes to EEPROM and flash with the
device. With some programmer and part combinations, flash (and sometimes
EEPROM, too) looks like a NOR memory, ie, one can only write 0 bits, not 1
bits. When this is detected, either page erase is deployed (eg, with parts
that have PDI/UPDI interfaces), or if that is not available, both EEPROM
and flash caches are fully read in, a pgm->chip_erase() command is issued
and both EEPROM and flash are written back to the device. Hence, it can
take minutes to ensure that a single previously cleared bit is set and,
therefore, this routine should be called sparingly.
avr_chip_erase_cached() erases the chip and discards pending writes() to
flash or EEPROM. It presets the flash cache to all 0xff alleviating the
need to read from the device flash. However, if the programmer serves
bootloaders (pgm->prog_modes & PM_SPM) then the flash cache is reset
instead, necessitating flash memory be fetched from the device on first
read; the reason for this is that bootloaders emulate chip erase and they
won't overwrite themselves (some bootloaders, eg, optiboot ignore chip
erase commands altogether) making it truly unknowable what the flash
contents on device is after a chip erase.
For EEPROM avr_chip_erase_cached() concludes that it has been deleted if a
previously cached EEPROM page that contained cleared bits now no longer
has these clear bits on the device. Only with this evidence is the EEPROM
cache preset to all 0xff otherwise the cache discards all pending writes
to EEPROM and is left unchanged otherwise.
Finally, avr_reset_cache() resets the cache without synchronising pending
writes() to the device.
2022-10-05 21:16:15 +00:00
|
|
|
last = done = 0;
|
2022-07-13 10:38:43 +00:00
|
|
|
}
|
|
|
|
|
Provide cached byte-wise read/write API (#1106)
* Provide cached byte-wise read/write API
int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char *value);
int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char data);
int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p);
int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p);
int avr_reset_cache(const PROGRAMMER *pgm, const AVRPART *p);
avr_read_byte_cached() and avr_write_byte_cached() use a cache if paged
routines are available and if the device memory is EEPROM or flash,
otherwise they fall back to pgm->read_byte() and pgm->write_byte(),
respectively. Byte-wise cached read always gets its data from the cache,
possibly after reading a page from the device memory. Byte-wise cached
write with an address in memory range only ever modifies the cache. Any
modifications are written to the device after calling avr_flush_cache() or
when attempting to read or write from a location outside the address range
of the device memory.
avr_flush_cache() synchronises pending writes to EEPROM and flash with the
device. With some programmer and part combinations, flash (and sometimes
EEPROM, too) looks like a NOR memory, ie, one can only write 0 bits, not 1
bits. When this is detected, either page erase is deployed (eg, with parts
that have PDI/UPDI interfaces), or if that is not available, both EEPROM
and flash caches are fully read in, a pgm->chip_erase() command is issued
and both EEPROM and flash are written back to the device. Hence, it can
take minutes to ensure that a single previously cleared bit is set and,
therefore, this routine should be called sparingly.
avr_chip_erase_cached() erases the chip and discards pending writes() to
flash or EEPROM. It presets the flash cache to all 0xff alleviating the
need to read from the device flash. However, if the programmer serves
bootloaders (pgm->prog_modes & PM_SPM) then the flash cache is reset
instead, necessitating flash memory be fetched from the device on first
read; the reason for this is that bootloaders emulate chip erase and they
won't overwrite themselves (some bootloaders, eg, optiboot ignore chip
erase commands altogether) making it truly unknowable what the flash
contents on device is after a chip erase.
For EEPROM avr_chip_erase_cached() concludes that it has been deleted if a
previously cached EEPROM page that contained cleared bits now no longer
has these clear bits on the device. Only with this evidence is the EEPROM
cache preset to all 0xff otherwise the cache discards all pending writes
to EEPROM and is left unchanged otherwise.
Finally, avr_reset_cache() resets the cache without synchronising pending
writes() to the device.
2022-10-05 21:16:15 +00:00
|
|
|
if(!done) {
|
|
|
|
for(int cnt = percent/2; cnt > last/2; cnt--)
|
|
|
|
avrdude_message(MSG_INFO, finish >= 0? "#": "-");
|
|
|
|
|
|
|
|
if(percent == 100) {
|
|
|
|
avrdude_message(MSG_INFO, " | %d%% %0.2fs", etime, finish >= 0? 100: last);
|
|
|
|
if(finish)
|
|
|
|
avrdude_message(MSG_INFO, "\n\n");
|
|
|
|
done = 1;
|
|
|
|
}
|
2022-07-13 10:38:43 +00:00
|
|
|
}
|
Provide cached byte-wise read/write API (#1106)
* Provide cached byte-wise read/write API
int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char *value);
int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char data);
int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p);
int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p);
int avr_reset_cache(const PROGRAMMER *pgm, const AVRPART *p);
avr_read_byte_cached() and avr_write_byte_cached() use a cache if paged
routines are available and if the device memory is EEPROM or flash,
otherwise they fall back to pgm->read_byte() and pgm->write_byte(),
respectively. Byte-wise cached read always gets its data from the cache,
possibly after reading a page from the device memory. Byte-wise cached
write with an address in memory range only ever modifies the cache. Any
modifications are written to the device after calling avr_flush_cache() or
when attempting to read or write from a location outside the address range
of the device memory.
avr_flush_cache() synchronises pending writes to EEPROM and flash with the
device. With some programmer and part combinations, flash (and sometimes
EEPROM, too) looks like a NOR memory, ie, one can only write 0 bits, not 1
bits. When this is detected, either page erase is deployed (eg, with parts
that have PDI/UPDI interfaces), or if that is not available, both EEPROM
and flash caches are fully read in, a pgm->chip_erase() command is issued
and both EEPROM and flash are written back to the device. Hence, it can
take minutes to ensure that a single previously cleared bit is set and,
therefore, this routine should be called sparingly.
avr_chip_erase_cached() erases the chip and discards pending writes() to
flash or EEPROM. It presets the flash cache to all 0xff alleviating the
need to read from the device flash. However, if the programmer serves
bootloaders (pgm->prog_modes & PM_SPM) then the flash cache is reset
instead, necessitating flash memory be fetched from the device on first
read; the reason for this is that bootloaders emulate chip erase and they
won't overwrite themselves (some bootloaders, eg, optiboot ignore chip
erase commands altogether) making it truly unknowable what the flash
contents on device is after a chip erase.
For EEPROM avr_chip_erase_cached() concludes that it has been deleted if a
previously cached EEPROM page that contained cleared bits now no longer
has these clear bits on the device. Only with this evidence is the EEPROM
cache preset to all 0xff otherwise the cache discards all pending writes
to EEPROM and is left unchanged otherwise.
Finally, avr_reset_cache() resets the cache without synchronising pending
writes() to the device.
2022-10-05 21:16:15 +00:00
|
|
|
last = percent;
|
2022-07-13 10:38:43 +00:00
|
|
|
|
Provide cached byte-wise read/write API (#1106)
* Provide cached byte-wise read/write API
int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char *value);
int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
AVRMEM *mem, unsigned long addr, unsigned char data);
int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p);
int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p);
int avr_reset_cache(const PROGRAMMER *pgm, const AVRPART *p);
avr_read_byte_cached() and avr_write_byte_cached() use a cache if paged
routines are available and if the device memory is EEPROM or flash,
otherwise they fall back to pgm->read_byte() and pgm->write_byte(),
respectively. Byte-wise cached read always gets its data from the cache,
possibly after reading a page from the device memory. Byte-wise cached
write with an address in memory range only ever modifies the cache. Any
modifications are written to the device after calling avr_flush_cache() or
when attempting to read or write from a location outside the address range
of the device memory.
avr_flush_cache() synchronises pending writes to EEPROM and flash with the
device. With some programmer and part combinations, flash (and sometimes
EEPROM, too) looks like a NOR memory, ie, one can only write 0 bits, not 1
bits. When this is detected, either page erase is deployed (eg, with parts
that have PDI/UPDI interfaces), or if that is not available, both EEPROM
and flash caches are fully read in, a pgm->chip_erase() command is issued
and both EEPROM and flash are written back to the device. Hence, it can
take minutes to ensure that a single previously cleared bit is set and,
therefore, this routine should be called sparingly.
avr_chip_erase_cached() erases the chip and discards pending writes() to
flash or EEPROM. It presets the flash cache to all 0xff alleviating the
need to read from the device flash. However, if the programmer serves
bootloaders (pgm->prog_modes & PM_SPM) then the flash cache is reset
instead, necessitating flash memory be fetched from the device on first
read; the reason for this is that bootloaders emulate chip erase and they
won't overwrite themselves (some bootloaders, eg, optiboot ignore chip
erase commands altogether) making it truly unknowable what the flash
contents on device is after a chip erase.
For EEPROM avr_chip_erase_cached() concludes that it has been deleted if a
previously cached EEPROM page that contained cleared bits now no longer
has these clear bits on the device. Only with this evidence is the EEPROM
cache preset to all 0xff otherwise the cache discards all pending writes
to EEPROM and is left unchanged otherwise.
Finally, avr_reset_cache() resets the cache without synchronising pending
writes() to the device.
2022-10-05 21:16:15 +00:00
|
|
|
setvbuf(stderr, (char *) NULL, _IOLBF, 0);
|
2022-07-13 10:38:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void terminal_setup_update_progress() {
|
|
|
|
if (isatty (STDERR_FILENO))
|
|
|
|
update_progress = update_progress_tty;
|
|
|
|
else {
|
|
|
|
update_progress = update_progress_no_tty;
|
|
|
|
/* disable all buffering of stderr for compatibility with
|
|
|
|
software that captures and redirects output to a GUI
|
|
|
|
i.e. Programmers Notepad */
|
|
|
|
setvbuf( stderr, NULL, _IONBF, 0 );
|
|
|
|
setvbuf( stdout, NULL, _IONBF, 0 );
|
|
|
|
}
|
|
|
|
}
|