Revamp terminal output: progress bar, callback and stdout/stderr (#1132)

* Print parms output to stdout
* Flush terminal writes and other minor changes
* Prepare terminal for periodic calls to programmer to reset bootloader WDT
* Only show progress reports for memories > 32 bytes or on -vv
* Freeze progress bar on serious error
* Allow cached r/w byte routines to be used in pgm->read_byte and pgm->write_byte
This commit is contained in:
Stefan Rueger 2022-10-23 21:56:45 +01:00 committed by GitHub
parent 34fa2faba5
commit 5b008a04cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 421 additions and 355 deletions

View File

@ -53,9 +53,9 @@ case "${ostype}" in
# Apple M1 (may be new version of homebrew also) # Apple M1 (may be new version of homebrew also)
if [ -d /opt/homebrew ] if [ -d /opt/homebrew ]
then then
build_flags="${build_flags} -D CMAKE_C_FLAGS=-I/opt/homebrew/include -D CMAKE_EXE_LINKER_FLAGS=-L/opt/homebrew/Cellar" build_flags="${build_flags} -D CMAKE_C_FLAGS=-I/opt/homebrew/include -D CMAKE_EXE_LINKER_FLAGS=-L/opt/homebrew/Cellar -D HAVE_LIBREADLINE:FILEPATH=/opt/homebrew/lib/libreadline.dylib"
else else
build_flags="${build_flags} -D CMAKE_C_FLAGS=-I/usr/local/include -D CMAKE_EXE_LINKER_FLAGS=-L/usr/local/Cellar" build_flags="${build_flags} -D CMAKE_C_FLAGS=-I/usr/local/include -D CMAKE_EXE_LINKER_FLAGS=-L/usr/local/Cellar -D HAVE_LIBREADLINE:FILEPATH=/usr/local/lib/libreadline.dylib"
fi fi
fi fi
;; ;;

View File

@ -1036,13 +1036,14 @@ int avr_write_mem(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m, int
int avr_signature(const PROGRAMMER *pgm, const AVRPART *p) { int avr_signature(const PROGRAMMER *pgm, const AVRPART *p) {
int rc; int rc;
report_progress (0,1,"Reading"); if(verbose > 1)
report_progress(0, 1, "Reading");
rc = avr_read(pgm, p, "signature", 0); rc = avr_read(pgm, p, "signature", 0);
if (rc < LIBAVRDUDE_SUCCESS) { if (rc < LIBAVRDUDE_SUCCESS) {
pmsg_error("unable to read signature data for part %s, rc=%d\n", p->desc, rc); pmsg_error("unable to read signature data for part %s, rc=%d\n", p->desc, rc);
return rc; return rc;
} }
report_progress (1,1,NULL); report_progress(1, 1, NULL);
return LIBAVRDUDE_SUCCESS; return LIBAVRDUDE_SUCCESS;
} }

View File

@ -126,6 +126,9 @@ int avr_has_paged_access(const PROGRAMMER *pgm, const AVRMEM *mem) {
} }
#define fallback_read_byte (pgm->read_byte != avr_read_byte_cached? pgm->read_byte: avr_read_byte_default)
#define fallback_write_byte (pgm->write_byte != avr_write_byte_cached? pgm->write_byte: avr_write_byte_default)
/* /*
* Read the page containing addr from the device into buf * Read the page containing addr from the device into buf
* - Caller to ensure buf has mem->page_size bytes * - Caller to ensure buf has mem->page_size bytes
@ -141,14 +144,14 @@ int avr_read_page_default(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM
unsigned char *pagecopy = cfg_malloc("avr_read_page_default()", pgsize); unsigned char *pagecopy = cfg_malloc("avr_read_page_default()", pgsize);
if(pgsize == 1) if(pgsize == 1)
return pgm->read_byte(pgm, p, mem, addr, buf); return fallback_read_byte(pgm, p, mem, addr, buf);
memcpy(pagecopy, mem->buf + base, pgsize); memcpy(pagecopy, mem->buf + base, pgsize);
if((rc = pgm->paged_load(pgm, p, mem, pgsize, base, pgsize)) >= 0) if((rc = pgm->paged_load(pgm, p, mem, pgsize, base, pgsize)) >= 0)
memcpy(buf, mem->buf + base, pgsize); memcpy(buf, mem->buf + base, pgsize);
memcpy(mem->buf + base, pagecopy, pgsize); memcpy(mem->buf + base, pagecopy, pgsize);
if(rc < 0) { if(rc < 0 && pgm->read_byte != avr_read_byte_cached) {
rc = LIBAVRDUDE_SUCCESS; rc = LIBAVRDUDE_SUCCESS;
for(int i=0; i<pgsize; i++) { for(int i=0; i<pgsize; i++) {
if(pgm->read_byte(pgm, p, mem, base+i, pagecopy+i) < 0) { if(pgm->read_byte(pgm, p, mem, base+i, pagecopy+i) < 0) {
@ -179,7 +182,7 @@ int avr_write_page_default(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM
unsigned char *pagecopy = cfg_malloc("avr_write_page_default()", pgsize); unsigned char *pagecopy = cfg_malloc("avr_write_page_default()", pgsize);
if(pgsize == 1) if(pgsize == 1)
return pgm->write_byte(pgm, p, mem, addr, *data); return fallback_write_byte(pgm, p, mem, addr, *data);
memcpy(pagecopy, mem->buf + base, pgsize); memcpy(pagecopy, mem->buf + base, pgsize);
memcpy(mem->buf + base, data, pgsize); memcpy(mem->buf + base, data, pgsize);
@ -261,18 +264,25 @@ static int loadCachePage(AVR_Cache *cp, const PROGRAMMER *pgm, const AVRPART *p,
static int writeCachePage(AVR_Cache *cp, const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, int base, int nlOnErr) { static int writeCachePage(AVR_Cache *cp, const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, int base, int nlOnErr) {
// Write modified page cont to device; if unsuccessful try bytewise access // Write modified page cont to device; if unsuccessful try bytewise access
if(avr_write_page_default(pgm, p, mem, base, cp->cont + base) < 0) { if(avr_write_page_default(pgm, p, mem, base, cp->cont + base) < 0) {
for(int i=0; i < cp->page_size; i++) if(pgm->read_byte != avr_read_byte_cached && pgm->write_byte != avr_write_byte_cached) {
if(cp->cont[base+i] != cp->copy[base+i]) for(int i=0; i < cp->page_size; i++)
if(pgm->write_byte(pgm, p, mem, base+i, cp->cont[base+i]) < 0 || if(cp->cont[base+i] != cp->copy[base+i])
pgm->read_byte(pgm, p, mem, base+i, cp->copy+base+i) < 0) { if(pgm->write_byte(pgm, p, mem, base+i, cp->cont[base+i]) < 0 ||
report_progress(1, -1, NULL); pgm->read_byte(pgm, p, mem, base+i, cp->copy+base+i) < 0) {
if(nlOnErr && quell_progress) report_progress(1, -1, NULL);
msg_info("\n"); if(nlOnErr && quell_progress)
pmsg_error("writeCachePage() %s access error at addr 0x%04x\n", mem->desc, base+i); msg_info("\n");
return LIBAVRDUDE_GENERAL_FAILURE; pmsg_error("%s access error at addr 0x%04x\n", mem->desc, base+i);
} return LIBAVRDUDE_GENERAL_FAILURE;
}
return LIBAVRDUDE_SUCCESS; // Bytewise writes & reads successful return LIBAVRDUDE_SUCCESS; // Bytewise writes & reads successful
}
report_progress(1, -1, NULL);
if(nlOnErr && quell_progress)
msg_info("\n");
pmsg_error("write %s page error at addr 0x%04x\n", mem->desc, base);
return LIBAVRDUDE_GENERAL_FAILURE;
} }
// Read page back from device and update copy to what is on device // Read page back from device and update copy to what is on device
if(avr_read_page_default(pgm, p, mem, base, cp->copy + base) < 0) { if(avr_read_page_default(pgm, p, mem, base, cp->copy + base) < 0) {
@ -552,7 +562,7 @@ int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *
// Use pgm->read_byte() if not EEPROM/flash or no paged access // Use pgm->read_byte() if not EEPROM/flash or no paged access
if(!avr_has_paged_access(pgm, mem)) if(!avr_has_paged_access(pgm, mem))
return pgm->read_byte(pgm, p, mem, addr, value); return fallback_read_byte(pgm, p, mem, addr, value);
// If address is out of range synchronise cache and, if successful, pretend reading a zero // If address is out of range synchronise cache and, if successful, pretend reading a zero
if(addr >= (unsigned long) mem->size) { if(addr >= (unsigned long) mem->size) {
@ -592,9 +602,9 @@ int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *
int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
unsigned long addr, unsigned char data) { unsigned long addr, unsigned char data) {
// Use pgm->read_byte() if not EEPROM/flash or no paged access // Use pgm->write_byte() if not EEPROM/flash or no paged access
if(!avr_has_paged_access(pgm, mem)) if(!avr_has_paged_access(pgm, mem))
return pgm->write_byte(pgm, p, mem, addr, data); return fallback_write_byte(pgm, p, mem, addr, data);
// If address is out of range synchronise caches with device and return whether successful // If address is out of range synchronise caches with device and return whether successful
if(addr >= (unsigned long) mem->size) if(addr >= (unsigned long) mem->size)
@ -687,7 +697,7 @@ int avr_page_erase_cached(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM
return LIBAVRDUDE_GENERAL_FAILURE; return LIBAVRDUDE_GENERAL_FAILURE;
if(mem->page_size == 1) { if(mem->page_size == 1) {
if(pgm->write_byte(pgm, p, mem, uaddr, 0xff) < 0) if(fallback_write_byte(pgm, p, mem, uaddr, 0xff) < 0)
return LIBAVRDUDE_GENERAL_FAILURE; return LIBAVRDUDE_GENERAL_FAILURE;
} else { } else {
if(!pgm->page_erase || pgm->page_erase(pgm, p, mem, uaddr) < 0) if(!pgm->page_erase || pgm->page_erase(pgm, p, mem, uaddr) < 0)

View File

@ -21,6 +21,8 @@
#ifndef avrdude_h #ifndef avrdude_h
#define avrdude_h #define avrdude_h
#include <stdio.h>
#define SYSTEM_CONF_FILE "avrdude.conf" #define SYSTEM_CONF_FILE "avrdude.conf"
#if defined(WIN32) #if defined(WIN32)
#define USER_CONF_FILE "avrdude.rc" #define USER_CONF_FILE "avrdude.rc"
@ -37,7 +39,7 @@ extern int verbose; // verbosity level (-v, -vv, ...)
extern int quell_progress; // quell progress report -q, reduce effective verbosity level (-qq, -qqq) extern int quell_progress; // quell progress report -q, reduce effective verbosity level (-qq, -qqq)
int avrdude_message(int msglvl, const char *format, ...); int avrdude_message(int msglvl, const char *format, ...);
int avrdude_message2(const char *fname, int msgmode, int msglvl, const char *format, ...); int avrdude_message2(FILE *fp, int lno, const char *file, const char *func, int msgmode, int msglvl, const char *format, ...);
#define MSG_EXT_ERROR (-3) // OS-type error, no -v option, can be suppressed with -qqqqq #define MSG_EXT_ERROR (-3) // OS-type error, no -v option, can be suppressed with -qqqqq
#define MSG_ERROR (-2) // Avrdude error, no -v option, can be suppressed with -qqqq #define MSG_ERROR (-2) // Avrdude error, no -v option, can be suppressed with -qqqq
@ -50,41 +52,45 @@ int avrdude_message2(const char *fname, int msgmode, int msglvl, const char *for
#define MSG_TRACE2 5 // Displayed with -vvvvv #define MSG_TRACE2 5 // Displayed with -vvvvv
#define MSG2_PROGNAME 1 // Start by printing progname #define MSG2_PROGNAME 1 // Start by printing progname
#define MSG2_FUNCTION 2 // Print calling function (1st arg) after progname #define MSG2_FUNCTION 2 // Print calling function (1st arg) after progname if >= notice
#define MSG2_TYPE 4 // Print message type after function or progname #define MSG2_FILELINE 4 // Print source file and line number after function if >= debug
#define MSG2_INDENT1 8 // Start by printing indentation of progname+1 blanks #define MSG2_TYPE 8 // Print message type after function or progname
#define MSG2_INDENT2 16 // Start by printing indentation of progname+2 blanks #define MSG2_INDENT1 16 // Start by printing indentation of progname+1 blanks
#define MSG2_FLUSH 32 // Flush before and after printing #define MSG2_INDENT2 32 // Start by printing indentation of progname+2 blanks
#define MSG2_FLUSH 64 // Flush before and after printing
// Shortcuts // Shortcuts
#define msg_ext_error(...) avrdude_message2(__func__, 0, MSG_EXT_ERROR, __VA_ARGS__) #define msg_ext_error(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, 0, MSG_EXT_ERROR, __VA_ARGS__)
#define msg_error(...) avrdude_message2(__func__, 0, MSG_ERROR, __VA_ARGS__) #define msg_error(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, 0, MSG_ERROR, __VA_ARGS__)
#define msg_warning(...) avrdude_message2(__func__, 0, MSG_WARNING, __VA_ARGS__) #define msg_warning(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, 0, MSG_WARNING, __VA_ARGS__)
#define msg_info(...) avrdude_message2(__func__, 0, MSG_INFO, __VA_ARGS__) #define msg_info(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, 0, MSG_INFO, __VA_ARGS__)
#define msg_notice(...) avrdude_message2(__func__, 0, MSG_NOTICE, __VA_ARGS__) #define msg_notice(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, 0, MSG_NOTICE, __VA_ARGS__)
#define msg_notice2(...) avrdude_message2(__func__, 0, MSG_NOTICE2, __VA_ARGS__) #define msg_notice2(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, 0, MSG_NOTICE2, __VA_ARGS__)
#define msg_debug(...) avrdude_message2(__func__, 0, MSG_DEBUG, __VA_ARGS__) #define msg_debug(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, 0, MSG_DEBUG, __VA_ARGS__)
#define msg_trace(...) avrdude_message2(__func__, 0, MSG_TRACE, __VA_ARGS__) #define msg_trace(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, 0, MSG_TRACE, __VA_ARGS__)
#define msg_trace2(...) avrdude_message2(__func__, 0, MSG_TRACE2, __VA_ARGS__) #define msg_trace2(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, 0, MSG_TRACE2, __VA_ARGS__)
#define pmsg_ext_error(...) avrdude_message2(__func__, MSG2_PROGNAME|MSG2_FUNCTION|MSG2_TYPE|MSG2_FLUSH, MSG_EXT_ERROR, __VA_ARGS__) #define pmsg_ext_error(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FUNCTION|MSG2_FILELINE|MSG2_TYPE|MSG2_FLUSH, MSG_EXT_ERROR, __VA_ARGS__)
#define pmsg_error(...) avrdude_message2(__func__, MSG2_PROGNAME|MSG2_FUNCTION|MSG2_TYPE|MSG2_FLUSH, MSG_ERROR, __VA_ARGS__) #define pmsg_error(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FUNCTION|MSG2_FILELINE|MSG2_TYPE|MSG2_FLUSH, MSG_ERROR, __VA_ARGS__)
#define pmsg_warning(...) avrdude_message2(__func__, MSG2_PROGNAME|MSG2_FUNCTION|MSG2_TYPE|MSG2_FLUSH, MSG_WARNING, __VA_ARGS__) #define pmsg_warning(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FUNCTION|MSG2_FILELINE|MSG2_TYPE|MSG2_FLUSH, MSG_WARNING, __VA_ARGS__)
#define pmsg_info(...) avrdude_message2(__func__, MSG2_PROGNAME|MSG2_FLUSH, MSG_INFO, __VA_ARGS__) #define pmsg_info(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FLUSH, MSG_INFO, __VA_ARGS__)
#define pmsg_notice(...) avrdude_message2(__func__, MSG2_PROGNAME|MSG2_FLUSH, MSG_NOTICE, __VA_ARGS__) #define pmsg_notice(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FLUSH, MSG_NOTICE, __VA_ARGS__)
#define pmsg_notice2(...) avrdude_message2(__func__, MSG2_PROGNAME|MSG2_FLUSH, MSG_NOTICE2, __VA_ARGS__) #define pmsg_notice2(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FLUSH, MSG_NOTICE2, __VA_ARGS__)
#define pmsg_debug(...) avrdude_message2(__func__, MSG2_PROGNAME|MSG2_FLUSH, MSG_DEBUG, __VA_ARGS__) #define pmsg_debug(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FLUSH, MSG_DEBUG, __VA_ARGS__)
#define pmsg_trace(...) avrdude_message2(__func__, MSG2_PROGNAME|MSG2_FLUSH, MSG_TRACE, __VA_ARGS__) #define pmsg_trace(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FLUSH, MSG_TRACE, __VA_ARGS__)
#define pmsg_trace2(...) avrdude_message2(__func__, MSG2_PROGNAME|MSG2_FLUSH, MSG_TRACE2, __VA_ARGS__) #define pmsg_trace2(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FLUSH, MSG_TRACE2, __VA_ARGS__)
#define imsg_ext_error(...) avrdude_message2(__func__, MSG2_INDENT1|MSG2_FLUSH, MSG_EXT_ERROR, __VA_ARGS__) #define imsg_ext_error(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT1|MSG2_FLUSH, MSG_EXT_ERROR, __VA_ARGS__)
#define imsg_error(...) avrdude_message2(__func__, MSG2_INDENT1|MSG2_FLUSH, MSG_ERROR, __VA_ARGS__) #define imsg_error(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT1|MSG2_FLUSH, MSG_ERROR, __VA_ARGS__)
#define imsg_warning(...) avrdude_message2(__func__, MSG2_INDENT1|MSG2_FLUSH, MSG_WARNING, __VA_ARGS__) #define imsg_warning(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT1|MSG2_FLUSH, MSG_WARNING, __VA_ARGS__)
#define imsg_info(...) avrdude_message2(__func__, MSG2_INDENT2|MSG2_FLUSH, MSG_INFO, __VA_ARGS__) #define imsg_info(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT2|MSG2_FLUSH, MSG_INFO, __VA_ARGS__)
#define imsg_notice(...) avrdude_message2(__func__, MSG2_INDENT2|MSG2_FLUSH, MSG_NOTICE, __VA_ARGS__) #define imsg_notice(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT2|MSG2_FLUSH, MSG_NOTICE, __VA_ARGS__)
#define imsg_notice2(...) avrdude_message2(__func__, MSG2_INDENT2|MSG2_FLUSH, MSG_NOTICE2, __VA_ARGS__) #define imsg_notice2(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT2|MSG2_FLUSH, MSG_NOTICE2, __VA_ARGS__)
#define imsg_debug(...) avrdude_message2(__func__, MSG2_INDENT2|MSG2_FLUSH, MSG_DEBUG, __VA_ARGS__) #define imsg_debug(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT2|MSG2_FLUSH, MSG_DEBUG, __VA_ARGS__)
#define imsg_trace(...) avrdude_message2(__func__, MSG2_INDENT2|MSG2_FLUSH, MSG_TRACE, __VA_ARGS__) #define imsg_trace(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT2|MSG2_FLUSH, MSG_TRACE, __VA_ARGS__)
#define imsg_trace2(...) avrdude_message2(__func__, MSG2_INDENT2|MSG2_FLUSH, MSG_TRACE2, __VA_ARGS__) #define imsg_trace2(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT2|MSG2_FLUSH, MSG_TRACE2, __VA_ARGS__)
#define term_out(...) avrdude_message2(stdout, __LINE__, __FILE__, __func__, MSG2_FLUSH, MSG_INFO, __VA_ARGS__)
#define fmsg_out(fp, ...) avrdude_message2(fp, __LINE__, __FILE__, __func__, MSG2_FLUSH, MSG_INFO, __VA_ARGS__)
#endif #endif

View File

@ -498,22 +498,15 @@ void avr_mem_display(const char *prefix, FILE *f, const AVRMEM *m,
int i, j; int i, j;
char * optr; char * optr;
if (m == NULL) { if (m == NULL || verbose > 2) {
fprintf(f, fprintf(f,
"%s Block Poll Page Polled\n" "%s Block Poll Page Polled\n"
"%sMemory Type Alias Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack\n" "%sMemory Type Alias Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack\n"
"%s----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------\n", "%s----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------\n",
prefix, prefix, prefix); prefix, prefix, prefix);
} }
else {
if (verbose > 2) {
fprintf(f,
"%s Block Poll Page Polled\n"
"%sMemory Type Alias Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack\n"
"%s----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------\n",
prefix, prefix, prefix);
}
if (m != NULL) {
// Only print memory section if the previous section printed isn't identical // Only print memory section if the previous section printed isn't identical
if(prev_mem_offset != m->offset || prev_mem_size != m->size || (strcmp(p->family_id, "") == 0)) { if(prev_mem_offset != m->offset || prev_mem_size != m->size || (strcmp(p->family_id, "") == 0)) {
prev_mem_offset = m->offset; prev_mem_offset = m->offset;

View File

@ -121,6 +121,8 @@ enum flip2_mem_unit {
FLIP2_MEM_UNIT_EXT_MEM_DF = 0x10 FLIP2_MEM_UNIT_EXT_MEM_DF = 0x10
}; };
#ifdef HAVE_LIBUSB
/* EXPORTED PROGRAMMER FUNCTION PROTOTYPES */ /* EXPORTED PROGRAMMER FUNCTION PROTOTYPES */
static int flip2_open(PROGRAMMER *pgm, const char *port_spec); static int flip2_open(PROGRAMMER *pgm, const char *port_spec);
@ -146,8 +148,6 @@ static void flip2_setup(PROGRAMMER * pgm);
static void flip2_teardown(PROGRAMMER * pgm); static void flip2_teardown(PROGRAMMER * pgm);
/* INTERNAL PROGRAMMER FUNCTION PROTOTYPES */ /* INTERNAL PROGRAMMER FUNCTION PROTOTYPES */
#ifdef HAVE_LIBUSB
// The internal ones are made conditional, as they're not defined further down #ifndef HAVE_LIBUSB
static void flip2_show_info(struct flip2 *flip2); static void flip2_show_info(struct flip2 *flip2);

View File

@ -103,7 +103,7 @@ static int jtag3_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM
static int jtag3_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, static int jtag3_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
unsigned long addr, unsigned char data); unsigned long addr, unsigned char data);
static int jtag3_set_sck_period(const PROGRAMMER *pgm, double v); static int jtag3_set_sck_period(const PROGRAMMER *pgm, double v);
void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p); void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp);
static int jtag3_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m, static int jtag3_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
unsigned int page_size, unsigned int page_size,
unsigned int addr, unsigned int n_bytes); unsigned int addr, unsigned int n_bytes);
@ -1077,7 +1077,7 @@ static int jtag3_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
if (PDATA(pgm)->set_sck(pgm, parm) < 0) if (PDATA(pgm)->set_sck(pgm, parm) < 0)
return -1; return -1;
} }
jtag3_print_parms1(pgm, progbuf); jtag3_print_parms1(pgm, progbuf, stderr);
if (conn == PARM3_CONN_JTAG) if (conn == PARM3_CONN_JTAG)
{ {
pmsg_notice2("jtag3_initialize(): " pmsg_notice2("jtag3_initialize(): "
@ -2333,12 +2333,12 @@ static void jtag3_display(const PROGRAMMER *pgm, const char *p) {
} }
void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p) { void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp) {
unsigned char buf[3]; unsigned char buf[3];
if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_VTARGET, buf, 2) < 0) if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_VTARGET, buf, 2) < 0)
return; return;
msg_info("%sVtarget %s: %.2f V\n", p, fmsg_out(fp, "%sVtarget %s: %.2f V\n", p,
verbose? "": " ", b2_to_u16(buf)/1000.0); verbose? "": " ", b2_to_u16(buf)/1000.0);
// Print features unique to the Power Debugger // Print features unique to the Power Debugger
@ -2350,7 +2350,7 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p) {
if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_VADJUST, buf, 2) < 0) if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_VADJUST, buf, 2) < 0)
return; return;
analog_raw_data = b2_to_u16(buf); analog_raw_data = b2_to_u16(buf);
msg_info("%sVout set %s: %.2f V\n", p, fmsg_out(fp, "%sVout set %s: %.2f V\n", p,
verbose? "": " ", analog_raw_data / 1000.0); verbose? "": " ", analog_raw_data / 1000.0);
// Read measured generator voltage value (VOUT) // Read measured generator voltage value (VOUT)
@ -2362,7 +2362,7 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p) {
else { else {
if (analog_raw_data & 0x0800) if (analog_raw_data & 0x0800)
analog_raw_data |= 0xF000; analog_raw_data |= 0xF000;
msg_info("%sVout measured %s: %.02f V\n", p, fmsg_out(fp, "%sVout measured %s: %.02f V\n", p,
verbose? "": " ", ((float) analog_raw_data / -200.0)); verbose? "": " ", ((float) analog_raw_data / -200.0));
} }
@ -2375,7 +2375,7 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p) {
else { else {
if (analog_raw_data & 0x0800) if (analog_raw_data & 0x0800)
analog_raw_data |= 0xF000; analog_raw_data |= 0xF000;
msg_info("%sCh A voltage %s: %.03f V\n", p, fmsg_out(fp, "%sCh A voltage %s: %.03f V\n", p,
verbose? "": " ", ((float) analog_raw_data / -200.0)); verbose? "": " ", ((float) analog_raw_data / -200.0));
} }
@ -2386,7 +2386,7 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p) {
if (buf[0] != 0x90) if (buf[0] != 0x90)
pmsg_error("invalid PARM3_ANALOG_A_CURRENT data packet format\n"); pmsg_error("invalid PARM3_ANALOG_A_CURRENT data packet format\n");
else else
msg_info("%sCh A current %s: %.3f mA\n", p, fmsg_out(fp, "%sCh A current %s: %.3f mA\n", p,
verbose? "": " ", (float) analog_raw_data * 0.003472); verbose? "": " ", (float) analog_raw_data * 0.003472);
// Read channel B voltage // Read channel B voltage
@ -2398,7 +2398,7 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p) {
else { else {
if (analog_raw_data & 0x0800) if (analog_raw_data & 0x0800)
analog_raw_data |= 0xF000; analog_raw_data |= 0xF000;
msg_info("%sCh B voltage %s: %.03f V\n", p, fmsg_out(fp, "%sCh B voltage %s: %.03f V\n", p,
verbose? "": " ", (float) analog_raw_data / -200.0); verbose? "": " ", (float) analog_raw_data / -200.0);
} }
@ -2411,7 +2411,7 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p) {
else { else {
if (analog_raw_data & 0x0800) if (analog_raw_data & 0x0800)
analog_raw_data |= 0xF000; analog_raw_data |= 0xF000;
msg_info("%sCh B current %s: %.3f mA\n", p, fmsg_out(fp, "%sCh B current %s: %.3f mA\n", p,
verbose? "": " ", (float) analog_raw_data * 0.555556); verbose? "": " ", (float) analog_raw_data * 0.555556);
} }
break; break;
@ -2422,33 +2422,33 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p) {
return; return;
if (b2_to_u16(buf) > 0) { if (b2_to_u16(buf) > 0) {
msg_info("%sJTAG clock megaAVR/program : %u kHz\n", p, b2_to_u16(buf)); fmsg_out(fp, "%sJTAG clock megaAVR/program : %u kHz\n", p, b2_to_u16(buf));
} }
if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_MEGA_DEBUG, buf, 2) < 0) if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_MEGA_DEBUG, buf, 2) < 0)
return; return;
if (b2_to_u16(buf) > 0) { if (b2_to_u16(buf) > 0) {
msg_info("%sJTAG clock megaAVR/debug : %u kHz\n", p, b2_to_u16(buf)); fmsg_out(fp, "%sJTAG clock megaAVR/debug : %u kHz\n", p, b2_to_u16(buf));
} }
if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_XMEGA_JTAG, buf, 2) < 0) if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_XMEGA_JTAG, buf, 2) < 0)
return; return;
if (b2_to_u16(buf) > 0) { if (b2_to_u16(buf) > 0) {
msg_info("%sJTAG clock Xmega : %u kHz\n", p, b2_to_u16(buf)); fmsg_out(fp, "%sJTAG clock Xmega : %u kHz\n", p, b2_to_u16(buf));
} }
if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_XMEGA_PDI, buf, 2) < 0) if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_XMEGA_PDI, buf, 2) < 0)
return; return;
if (b2_to_u16(buf) > 0) { if (b2_to_u16(buf) > 0) {
msg_info("%sPDI/UPDI clock Xmega/megaAVR : %u kHz\n", p, b2_to_u16(buf)); fmsg_out(fp, "%sPDI/UPDI clock Xmega/megaAVR : %u kHz\n", p, b2_to_u16(buf));
} }
} }
static void jtag3_print_parms(const PROGRAMMER *pgm) { static void jtag3_print_parms(const PROGRAMMER *pgm, FILE *fp) {
jtag3_print_parms1(pgm, ""); jtag3_print_parms1(pgm, "", fp);
} }
static unsigned char jtag3_memtype(const PROGRAMMER *pgm, const AVRPART *p, unsigned long addr) { static unsigned char jtag3_memtype(const PROGRAMMER *pgm, const AVRPART *p, unsigned long addr) {

View File

@ -38,7 +38,7 @@ int jtag3_setparm(const PROGRAMMER *pgm, unsigned char scope,
unsigned char *value, unsigned char length); unsigned char *value, unsigned char length);
int jtag3_command(const PROGRAMMER *pgm, unsigned char *cmd, unsigned int cmdlen, int jtag3_command(const PROGRAMMER *pgm, unsigned char *cmd, unsigned int cmdlen,
unsigned char **resp, const char *descr); unsigned char **resp, const char *descr);
void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p); void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp);
int jtag3_set_vtarget(const PROGRAMMER *pgm, double voltage); int jtag3_set_vtarget(const PROGRAMMER *pgm, double voltage);
extern const char jtag3_desc[]; extern const char jtag3_desc[];
extern const char jtag3_dw_desc[]; extern const char jtag3_dw_desc[];

View File

@ -104,7 +104,7 @@ static int jtagmkI_getparm(const PROGRAMMER *pgm, unsigned char parm,
unsigned char * value); unsigned char * value);
static int jtagmkI_setparm(const PROGRAMMER *pgm, unsigned char parm, static int jtagmkI_setparm(const PROGRAMMER *pgm, unsigned char parm,
unsigned char value); unsigned char value);
static void jtagmkI_print_parms1(const PROGRAMMER *pgm, const char *p); static void jtagmkI_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp);
static int jtagmkI_resync(const PROGRAMMER *pgm, int maxtries, int signon); static int jtagmkI_resync(const PROGRAMMER *pgm, int maxtries, int signon);
@ -1170,13 +1170,13 @@ static void jtagmkI_display(const PROGRAMMER *pgm, const char *p) {
msg_info("%sICE HW version: 0x%02x\n", p, hw); msg_info("%sICE HW version: 0x%02x\n", p, hw);
msg_info("%sICE FW version: 0x%02x\n", p, fw); msg_info("%sICE FW version: 0x%02x\n", p, fw);
jtagmkI_print_parms1(pgm, p); jtagmkI_print_parms1(pgm, p, stderr);
return; return;
} }
static void jtagmkI_print_parms1(const PROGRAMMER *pgm, const char *p) { static void jtagmkI_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp) {
unsigned char vtarget, jtag_clock; unsigned char vtarget, jtag_clock;
const char *clkstr; const char *clkstr;
double clk; double clk;
@ -1211,15 +1211,15 @@ static void jtagmkI_print_parms1(const PROGRAMMER *pgm, const char *p) {
clk = 1e6; clk = 1e6;
} }
msg_info("%sVtarget : %.1f V\n", p, 6.25 * (unsigned)vtarget / 255.0); fmsg_out(fp, "%sVtarget : %.1f V\n", p, 6.25 * (unsigned)vtarget / 255.0);
msg_info("%sJTAG clock : %s (%.1f us)\n", p, clkstr, 1.0e6 / clk); fmsg_out(fp, "%sJTAG clock : %s (%.1f us)\n", p, clkstr, 1.0e6 / clk);
return; return;
} }
static void jtagmkI_print_parms(const PROGRAMMER *pgm) { static void jtagmkI_print_parms(const PROGRAMMER *pgm, FILE *fp) {
jtagmkI_print_parms1(pgm, ""); jtagmkI_print_parms1(pgm, "", fp);
} }
const char jtagmkI_desc[] = "Atmel JTAG ICE mkI"; const char jtagmkI_desc[] = "Atmel JTAG ICE mkI";

View File

@ -144,7 +144,7 @@ static int jtagmkII_reset(const PROGRAMMER *pgm, unsigned char flags);
static int jtagmkII_set_sck_period(const PROGRAMMER *pgm, double v); static int jtagmkII_set_sck_period(const PROGRAMMER *pgm, double v);
static int jtagmkII_setparm(const PROGRAMMER *pgm, unsigned char parm, static int jtagmkII_setparm(const PROGRAMMER *pgm, unsigned char parm,
unsigned char * value); unsigned char * value);
static void jtagmkII_print_parms1(const PROGRAMMER *pgm, const char *p); static void jtagmkII_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp);
static int jtagmkII_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m, static int jtagmkII_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
unsigned int page_size, unsigned int page_size,
unsigned int addr, unsigned int n_bytes); unsigned int addr, unsigned int n_bytes);
@ -2508,13 +2508,13 @@ static void jtagmkII_display(const PROGRAMMER *pgm, const char *p) {
PDATA(pgm)->serno[0], PDATA(pgm)->serno[1], PDATA(pgm)->serno[2], PDATA(pgm)->serno[0], PDATA(pgm)->serno[1], PDATA(pgm)->serno[2],
PDATA(pgm)->serno[3], PDATA(pgm)->serno[4], PDATA(pgm)->serno[5]); PDATA(pgm)->serno[3], PDATA(pgm)->serno[4], PDATA(pgm)->serno[5]);
jtagmkII_print_parms1(pgm, p); jtagmkII_print_parms1(pgm, p, stderr);
return; return;
} }
static void jtagmkII_print_parms1(const PROGRAMMER *pgm, const char *p) { static void jtagmkII_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp) {
unsigned char vtarget[4], jtag_clock[4]; unsigned char vtarget[4], jtag_clock[4];
char clkbuf[20]; char clkbuf[20];
double clk; double clk;
@ -2522,7 +2522,7 @@ static void jtagmkII_print_parms1(const PROGRAMMER *pgm, const char *p) {
if (jtagmkII_getparm(pgm, PAR_OCD_VTARGET, vtarget) < 0) if (jtagmkII_getparm(pgm, PAR_OCD_VTARGET, vtarget) < 0)
return; return;
msg_info("%sVtarget : %.1f V\n", p, b2_to_u16(vtarget) / 1000.0); fmsg_out(fp, "%sVtarget : %.1f V\n", p, b2_to_u16(vtarget) / 1000.0);
if ((pgm->flag & PGM_FL_IS_JTAG)) { if ((pgm->flag & PGM_FL_IS_JTAG)) {
if (jtagmkII_getparm(pgm, PAR_OCD_JTAG_CLK, jtag_clock) < 0) if (jtagmkII_getparm(pgm, PAR_OCD_JTAG_CLK, jtag_clock) < 0)
@ -2541,15 +2541,15 @@ static void jtagmkII_print_parms1(const PROGRAMMER *pgm, const char *p) {
sprintf(clkbuf, "%.1f kHz", 5.35e3 / (double)jtag_clock[0]); sprintf(clkbuf, "%.1f kHz", 5.35e3 / (double)jtag_clock[0]);
clk = 5.35e6 / (double)jtag_clock[0]; clk = 5.35e6 / (double)jtag_clock[0];
msg_info("%sJTAG clock : %s (%.1f us)\n", p, clkbuf, 1.0e6 / clk); fmsg_out(fp, "%sJTAG clock : %s (%.1f us)\n", p, clkbuf, 1.0e6 / clk);
} }
} }
return; return;
} }
static void jtagmkII_print_parms(const PROGRAMMER *pgm) { static void jtagmkII_print_parms(const PROGRAMMER *pgm, FILE *fp) {
jtagmkII_print_parms1(pgm, ""); jtagmkII_print_parms1(pgm, "", fp);
} }
static unsigned char jtagmkII_memtype(const PROGRAMMER *pgm, const AVRPART *p, unsigned long addr) { static unsigned char jtagmkII_memtype(const PROGRAMMER *pgm, const AVRPART *p, unsigned long addr) {

View File

@ -783,7 +783,8 @@ typedef struct programmer_t {
unsigned long addr, unsigned char *value); unsigned long addr, unsigned char *value);
int (*read_sig_bytes) (const struct programmer_t *pgm, const AVRPART *p, const AVRMEM *m); int (*read_sig_bytes) (const struct programmer_t *pgm, const AVRPART *p, const AVRMEM *m);
int (*read_sib) (const struct programmer_t *pgm, const AVRPART *p, char *sib); int (*read_sib) (const struct programmer_t *pgm, const AVRPART *p, char *sib);
void (*print_parms) (const struct programmer_t *pgm); int (*term_keep_alive)(const struct programmer_t *pgm, const AVRPART *p);
void (*print_parms) (const struct programmer_t *pgm, FILE *fp);
int (*set_vtarget) (const struct programmer_t *pgm, double v); int (*set_vtarget) (const struct programmer_t *pgm, double v);
int (*set_varef) (const struct programmer_t *pgm, unsigned int chan, double v); int (*set_varef) (const struct programmer_t *pgm, unsigned int chan, double v);
int (*set_fosc) (const struct programmer_t *pgm, double v); int (*set_fosc) (const struct programmer_t *pgm, double v);

View File

@ -87,36 +87,48 @@ static const char *avrdude_message_type(int msglvl) {
} }
} }
int avrdude_message2(const char *fname, int msgmode, int msglvl, const char *format, ...) { int avrdude_message2(FILE *fp, int lno, const char *file, const char *func, int msgmode, int msglvl, const char *format, ...) {
int rc = 0; int rc = 0;
va_list ap; va_list ap;
if(msglvl <= MSG_ERROR) // Serious error? Freee progress bars (if any)
report_progress(1, -1, NULL);
if(msgmode & MSG2_FLUSH) { if(msgmode & MSG2_FLUSH) {
fflush(stdout); fflush(stdout);
fflush(stderr); fflush(stderr);
} }
// Reduce effective verbosity level by number of -q above one // Reduce effective verbosity level by number of -q above one when printing to stderr
if ((quell_progress < 2? verbose: verbose+1-quell_progress) >= msglvl) { if ((quell_progress < 2 || fp != stderr? verbose: verbose+1-quell_progress) >= msglvl) {
if(msgmode & MSG2_PROGNAME) { if(msgmode & MSG2_PROGNAME) {
fprintf(stderr, "%s", progname); fprintf(fp, "%s", progname);
if(verbose >= MSG_NOTICE && (msgmode & MSG2_FUNCTION)) if(verbose >= MSG_NOTICE && (msgmode & MSG2_FUNCTION))
fprintf(stderr, " %s()", fname); fprintf(fp, " %s()", func);
if(verbose >= MSG_DEBUG && (msgmode & MSG2_FILELINE)) {
const char *pr = strrchr(file, '/'); // only print basename
#if defined (WIN32)
if(!pr)
pr = strrchr(file, '\\');
#endif
pr = pr? pr+1: file;
fprintf(fp, " [%s:%d]", pr, lno);
}
if(msgmode & MSG2_TYPE) if(msgmode & MSG2_TYPE)
fprintf(stderr, " %s", avrdude_message_type(msglvl)); fprintf(fp, " %s", avrdude_message_type(msglvl));
fprintf(stderr, ": "); fprintf(fp, ": ");
} else if(msgmode & MSG2_INDENT1) { } else if(msgmode & MSG2_INDENT1) {
fprintf(stderr, "%*s", (int) strlen(progname)+1, ""); fprintf(fp, "%*s", (int) strlen(progname)+1, "");
} else if(msgmode & MSG2_INDENT2) { } else if(msgmode & MSG2_INDENT2) {
fprintf(stderr, "%*s", (int) strlen(progname)+2, ""); fprintf(fp, "%*s", (int) strlen(progname)+2, "");
} }
va_start(ap, format); va_start(ap, format);
rc = vfprintf(stderr, format, ap); rc = vfprintf(fp, format, ap);
va_end(ap); va_end(ap);
} }
if(msgmode & MSG2_FLUSH) if(msgmode & MSG2_FLUSH)
fflush(stderr); fflush(fp);
return rc; return rc;
} }

View File

@ -140,6 +140,7 @@ PROGRAMMER *pgm_new(void) {
pgm->write_setup = NULL; pgm->write_setup = NULL;
pgm->read_sig_bytes = NULL; pgm->read_sig_bytes = NULL;
pgm->read_sib = NULL; pgm->read_sib = NULL;
pgm->term_keep_alive= NULL;
pgm->print_parms = NULL; pgm->print_parms = NULL;
pgm->set_vtarget = NULL; pgm->set_vtarget = NULL;
pgm->set_varef = NULL; pgm->set_varef = NULL;

View File

@ -47,7 +47,7 @@
static int stk500_getparm(const PROGRAMMER *pgm, unsigned parm, unsigned *value); static int stk500_getparm(const PROGRAMMER *pgm, unsigned parm, unsigned *value);
static int stk500_setparm(const PROGRAMMER *pgm, unsigned parm, unsigned value); static int stk500_setparm(const PROGRAMMER *pgm, unsigned parm, unsigned value);
static void stk500_print_parms1(const PROGRAMMER *pgm, const char *p); static void stk500_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp);
static int stk500_send(const PROGRAMMER *pgm, unsigned char *buf, size_t len) { static int stk500_send(const PROGRAMMER *pgm, unsigned char *buf, size_t len) {
@ -1160,13 +1160,13 @@ static void stk500_display(const PROGRAMMER *pgm, const char *p) {
msg_info("%sTopcard : %s\n", p, n); msg_info("%sTopcard : %s\n", p, n);
} }
if(strcmp(pgm->type, "Arduino") != 0) if(strcmp(pgm->type, "Arduino") != 0)
stk500_print_parms1(pgm, p); stk500_print_parms1(pgm, p, stderr);
return; return;
} }
static void stk500_print_parms1(const PROGRAMMER *pgm, const char *p) { static void stk500_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp) {
unsigned vtarget, vadjust, osc_pscale, osc_cmatch, sck_duration; unsigned vtarget, vadjust, osc_pscale, osc_cmatch, sck_duration;
stk500_getparm(pgm, Parm_STK_VTARGET, &vtarget); stk500_getparm(pgm, Parm_STK_VTARGET, &vtarget);
@ -1175,11 +1175,11 @@ static void stk500_print_parms1(const PROGRAMMER *pgm, const char *p) {
stk500_getparm(pgm, Parm_STK_OSC_CMATCH, &osc_cmatch); stk500_getparm(pgm, Parm_STK_OSC_CMATCH, &osc_cmatch);
stk500_getparm(pgm, Parm_STK_SCK_DURATION, &sck_duration); stk500_getparm(pgm, Parm_STK_SCK_DURATION, &sck_duration);
msg_info("%sVtarget : %.1f V\n", p, vtarget / 10.0); fmsg_out(fp, "%sVtarget : %.1f V\n", p, vtarget / 10.0);
msg_info("%sVaref : %.1f V\n", p, vadjust / 10.0); fmsg_out(fp, "%sVaref : %.1f V\n", p, vadjust / 10.0);
msg_info("%sOscillator : ", p); fmsg_out(fp, "%sOscillator : ", p);
if (osc_pscale == 0) if (osc_pscale == 0)
msg_info("Off\n"); fmsg_out(fp, "Off\n");
else { else {
int prescale = 1; int prescale = 1;
double f = STK500_XTAL / 2; double f = STK500_XTAL / 2;
@ -1203,16 +1203,16 @@ static void stk500_print_parms1(const PROGRAMMER *pgm, const char *p) {
unit = "kHz"; unit = "kHz";
} else } else
unit = "Hz"; unit = "Hz";
msg_info("%.3f %s\n", f, unit); fmsg_out(fp, "%.3f %s\n", f, unit);
} }
msg_info("%sSCK period : %.1f us\n", p, sck_duration * 8.0e6 / STK500_XTAL + 0.05); fmsg_out(fp, "%sSCK period : %.1f us\n", p, sck_duration * 8.0e6 / STK500_XTAL + 0.05);
return; return;
} }
static void stk500_print_parms(const PROGRAMMER *pgm) { static void stk500_print_parms(const PROGRAMMER *pgm, FILE *fp) {
stk500_print_parms1(pgm, ""); stk500_print_parms1(pgm, "", fp);
} }
static void stk500_setup(PROGRAMMER * pgm) static void stk500_setup(PROGRAMMER * pgm)

View File

@ -262,7 +262,7 @@ static int stk500v2_setparm(const PROGRAMMER *pgm, unsigned char parm, unsigned
static int stk500v2_getparm2(const PROGRAMMER *pgm, unsigned char parm, unsigned int *value); static int stk500v2_getparm2(const PROGRAMMER *pgm, unsigned char parm, unsigned int *value);
static int stk500v2_setparm2(const PROGRAMMER *pgm, unsigned char parm, unsigned int value); static int stk500v2_setparm2(const PROGRAMMER *pgm, unsigned char parm, unsigned int value);
static int stk500v2_setparm_real(const PROGRAMMER *pgm, unsigned char parm, unsigned char value); static int stk500v2_setparm_real(const PROGRAMMER *pgm, unsigned char parm, unsigned char value);
static void stk500v2_print_parms1(const PROGRAMMER *pgm, const char *p); static void stk500v2_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp);
static int stk500v2_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m, static int stk500v2_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
unsigned int page_size, unsigned int page_size,
unsigned int addr, unsigned int n_bytes); unsigned int addr, unsigned int n_bytes);
@ -3075,7 +3075,7 @@ static void stk500v2_display(const PROGRAMMER *pgm, const char *p) {
stk500v2_getparm2(pgm, PARAM2_EC_ID_TABLE_REV, &rev); stk500v2_getparm2(pgm, PARAM2_EC_ID_TABLE_REV, &rev);
msg_info("%sEC_ID table rev : %d\n", p, rev); msg_info("%sEC_ID table rev : %d\n", p, rev);
} }
stk500v2_print_parms1(pgm, p); stk500v2_print_parms1(pgm, p, stderr);
return; return;
} }
@ -3095,7 +3095,7 @@ f_to_kHz_MHz(double f, const char **unit)
return f; return f;
} }
static void stk500v2_print_parms1(const PROGRAMMER *pgm, const char *p) { static void stk500v2_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp) {
unsigned char vtarget = 0, vadjust = 0, osc_pscale = 0, osc_cmatch = 0, sck_duration =0; //XXX 0 is not correct, check caller unsigned char vtarget = 0, vadjust = 0, osc_pscale = 0, osc_cmatch = 0, sck_duration =0; //XXX 0 is not correct, check caller
unsigned int sck_stk600, clock_conf, dac, oct, varef; unsigned int sck_stk600, clock_conf, dac, oct, varef;
unsigned char vtarget_jtag[4]; unsigned char vtarget_jtag[4];
@ -3110,8 +3110,7 @@ static void stk500v2_print_parms1(const PROGRAMMER *pgm, const char *p) {
pgmcp->cookie = PDATA(pgm)->chained_pdata; pgmcp->cookie = PDATA(pgm)->chained_pdata;
jtagmkII_getparm(pgmcp, PAR_OCD_VTARGET, vtarget_jtag); jtagmkII_getparm(pgmcp, PAR_OCD_VTARGET, vtarget_jtag);
pgm_free(pgmcp); pgm_free(pgmcp);
msg_info("%sVtarget : %.1f V\n", p, fmsg_out(fp, "%sVtarget : %.1f V\n", p, b2_to_u16(vtarget_jtag) / 1000.0);
b2_to_u16(vtarget_jtag) / 1000.0);
} else if (PDATA(pgm)->pgmtype == PGMTYPE_JTAGICE3) { } else if (PDATA(pgm)->pgmtype == PGMTYPE_JTAGICE3) {
PROGRAMMER *pgmcp = pgm_dup(pgm); PROGRAMMER *pgmcp = pgm_dup(pgm);
pgmcp->cookie = PDATA(pgm)->chained_pdata; pgmcp->cookie = PDATA(pgm)->chained_pdata;
@ -3119,11 +3118,11 @@ static void stk500v2_print_parms1(const PROGRAMMER *pgm, const char *p) {
// Copy pgm->id contents over to pgmcp->id // Copy pgm->id contents over to pgmcp->id
for(LNODEID ln=lfirst(pgm->id); ln; ln=lnext(ln)) for(LNODEID ln=lfirst(pgm->id); ln; ln=lnext(ln))
ladd(pgmcp->id, cfg_strdup("stk500v2_print_parms1()", ldata(ln))); ladd(pgmcp->id, cfg_strdup("stk500v2_print_parms1()", ldata(ln)));
jtag3_print_parms1(pgmcp, p); jtag3_print_parms1(pgmcp, p, fp);
pgm_free(pgmcp); pgm_free(pgmcp);
} else { } else {
stk500v2_getparm(pgm, PARAM_VTARGET, &vtarget); stk500v2_getparm(pgm, PARAM_VTARGET, &vtarget);
msg_info("%sVtarget : %.1f V\n", p, vtarget / 10.0); fmsg_out(fp, "%sVtarget : %.1f V\n", p, vtarget / 10.0);
} }
switch (PDATA(pgm)->pgmtype) { switch (PDATA(pgm)->pgmtype) {
@ -3132,12 +3131,12 @@ static void stk500v2_print_parms1(const PROGRAMMER *pgm, const char *p) {
stk500v2_getparm(pgm, PARAM_VADJUST, &vadjust); stk500v2_getparm(pgm, PARAM_VADJUST, &vadjust);
stk500v2_getparm(pgm, PARAM_OSC_PSCALE, &osc_pscale); stk500v2_getparm(pgm, PARAM_OSC_PSCALE, &osc_pscale);
stk500v2_getparm(pgm, PARAM_OSC_CMATCH, &osc_cmatch); stk500v2_getparm(pgm, PARAM_OSC_CMATCH, &osc_cmatch);
msg_info("%sSCK period : %.1f us\n", p, fmsg_out(fp, "%sSCK period : %.1f us\n", p,
stk500v2_sck_to_us(pgm, sck_duration)); stk500v2_sck_to_us(pgm, sck_duration));
msg_info("%sVaref : %.1f V\n", p, vadjust / 10.0); fmsg_out(fp, "%sVaref : %.1f V\n", p, vadjust / 10.0);
msg_info("%sOscillator : ", p); fmsg_out(fp, "%sOscillator : ", p);
if (osc_pscale == 0) if (osc_pscale == 0)
msg_info("Off\n"); fmsg_out(fp, "Off\n");
else { else {
prescale = 1; prescale = 1;
f = STK500V2_XTAL / 2; f = STK500V2_XTAL / 2;
@ -3153,14 +3152,14 @@ static void stk500v2_print_parms1(const PROGRAMMER *pgm, const char *p) {
f /= prescale; f /= prescale;
f /= (osc_cmatch + 1); f /= (osc_cmatch + 1);
f = f_to_kHz_MHz(f, &unit); f = f_to_kHz_MHz(f, &unit);
msg_info("%.3f %s\n", f, unit); fmsg_out(fp, "%.3f %s\n", f, unit);
} }
break; break;
case PGMTYPE_AVRISP_MKII: case PGMTYPE_AVRISP_MKII:
case PGMTYPE_JTAGICE_MKII: case PGMTYPE_JTAGICE_MKII:
stk500v2_getparm(pgm, PARAM_SCK_DURATION, &sck_duration); stk500v2_getparm(pgm, PARAM_SCK_DURATION, &sck_duration);
msg_info("%sSCK period : %.2f us\n", p, fmsg_out(fp, "%sSCK period : %.2f us\n", p,
(float) 1000000 / avrispmkIIfreqs[sck_duration]); (float) 1000000 / avrispmkIIfreqs[sck_duration]);
break; break;
@ -3172,7 +3171,7 @@ static void stk500v2_print_parms1(const PROGRAMMER *pgm, const char *p) {
if (stk500v2_jtag3_send(pgm, cmd, 1) >= 0 && if (stk500v2_jtag3_send(pgm, cmd, 1) >= 0 &&
stk500v2_jtag3_recv(pgm, cmd, 4) >= 2) { stk500v2_jtag3_recv(pgm, cmd, 4) >= 2) {
unsigned int sck = cmd[1] | (cmd[2] << 8); unsigned int sck = cmd[1] | (cmd[2] << 8);
msg_info("%sSCK period : %.2f us\n", p, fmsg_out(fp, "%sSCK period : %.2f us\n", p,
(float)(1E6 / (1000.0 * sck))); (float)(1E6 / (1000.0 * sck)));
} }
} }
@ -3180,23 +3179,23 @@ static void stk500v2_print_parms1(const PROGRAMMER *pgm, const char *p) {
case PGMTYPE_STK600: case PGMTYPE_STK600:
stk500v2_getparm2(pgm, PARAM2_AREF0, &varef); stk500v2_getparm2(pgm, PARAM2_AREF0, &varef);
msg_info("%sVaref 0 : %.2f V\n", p, varef / 100.0); fmsg_out(fp, "%sVaref 0 : %.2f V\n", p, varef / 100.0);
stk500v2_getparm2(pgm, PARAM2_AREF1, &varef); stk500v2_getparm2(pgm, PARAM2_AREF1, &varef);
msg_info("%sVaref 1 : %.2f V\n", p, varef / 100.0); fmsg_out(fp, "%sVaref 1 : %.2f V\n", p, varef / 100.0);
stk500v2_getparm2(pgm, PARAM2_SCK_DURATION, &sck_stk600); stk500v2_getparm2(pgm, PARAM2_SCK_DURATION, &sck_stk600);
msg_info("%sSCK period : %.2f us\n", p, fmsg_out(fp, "%sSCK period : %.2f us\n", p,
(float) (sck_stk600 + 1) / 8.0); (float) (sck_stk600 + 1) / 8.0);
stk500v2_getparm2(pgm, PARAM2_CLOCK_CONF, &clock_conf); stk500v2_getparm2(pgm, PARAM2_CLOCK_CONF, &clock_conf);
oct = (clock_conf & 0xf000) >> 12u; oct = (clock_conf & 0xf000) >> 12u;
dac = (clock_conf & 0x0ffc) >> 2u; dac = (clock_conf & 0x0ffc) >> 2u;
f = pow(2, (double)oct) * 2078.0 / (2 - (double)dac / 1024.0); f = pow(2, (double)oct) * 2078.0 / (2 - (double)dac / 1024.0);
f = f_to_kHz_MHz(f, &unit); f = f_to_kHz_MHz(f, &unit);
msg_info("%sOscillator : %.3f %s\n", fmsg_out(fp, "%sOscillator : %.3f %s\n",
p, f, unit); p, f, unit);
break; break;
default: default:
msg_info("%sSCK period : %.1f us\n", p, fmsg_out(fp, "%sSCK period : %.1f us\n", p,
sck_duration * 8.0e6 / STK500V2_XTAL + 0.05); sck_duration * 8.0e6 / STK500V2_XTAL + 0.05);
break; break;
} }
@ -3205,8 +3204,8 @@ static void stk500v2_print_parms1(const PROGRAMMER *pgm, const char *p) {
} }
static void stk500v2_print_parms(const PROGRAMMER *pgm) { static void stk500v2_print_parms(const PROGRAMMER *pgm, FILE *fp) {
stk500v2_print_parms1(pgm, ""); stk500v2_print_parms1(pgm, "", fp);
} }
static int stk500v2_perform_osccal(const PROGRAMMER *pgm) { static int stk500v2_perform_osccal(const PROGRAMMER *pgm) {

View File

@ -33,10 +33,21 @@
#include <errno.h> #include <errno.h>
#if defined(HAVE_LIBREADLINE) #if defined(HAVE_LIBREADLINE)
# include <readline/readline.h> #include <readline/readline.h>
# include <readline/history.h> #include <readline/history.h>
#ifdef _MSC_VER
#include "msvc/unistd.h"
#else
#include <unistd.h>
#endif #endif
#ifdef WIN32
#include <windows.h>
#endif
#endif
#include "avrdude.h" #include "avrdude.h"
#include "term.h" #include "term.h"
@ -114,7 +125,7 @@ static int nexttok(char *buf, char **tok, char **next) {
n = q; n = q;
uint8_t quotes = 0; uint8_t quotes = 0;
while (*n && (!isspace(*n) || quotes)) { while (*n && (!isspace(*n) || quotes)) {
// poor man's quote and escape processing // Poor man's quote and escape processing
if (*n == '"' || *n == '\'') if (*n == '"' || *n == '\'')
quotes++; quotes++;
else if(*n == '\\' && n[1]) else if(*n == '\\' && n[1])
@ -173,7 +184,7 @@ static int chardump_line(char *buffer, unsigned char *p, int n, int pad) {
int i; int i;
unsigned char b[128]; unsigned char b[128];
// sanity check // Sanity check
n = n < 1? 1: n > sizeof b? sizeof b: n; n = n < 1? 1: n > sizeof b? sizeof b: n;
memcpy(b, p, n); memcpy(b, p, n);
@ -202,7 +213,7 @@ static int hexdump_buf(FILE *f, int startaddr, unsigned char *buf, int len) {
n = len; n = len;
hexdump_line(dst1, p, n, 48); hexdump_line(dst1, p, n, 48);
chardump_line(dst2, p, n, 16); chardump_line(dst2, p, n, 16);
fprintf(f, "%04x %s |%s|\n", addr, dst1, dst2); term_out("%04x %s |%s|\n", addr, dst1, dst2);
len -= n; len -= n;
addr += n; addr += n;
p += n; p += n;
@ -214,7 +225,7 @@ static int hexdump_buf(FILE *f, int startaddr, unsigned char *buf, int len) {
static int cmd_dump(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { static int cmd_dump(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
if (argc < 2 || argc > 4) { if (argc < 2 || argc > 4) {
terminal_message(MSG_INFO, msg_error(
"Usage: %s <memory> <addr> <len>\n" "Usage: %s <memory> <addr> <len>\n"
" %s <memory> <addr> ...\n" " %s <memory> <addr> ...\n"
" %s <memory> <addr>\n" " %s <memory> <addr>\n"
@ -229,8 +240,7 @@ static int cmd_dump(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
char *memtype = argv[1]; char *memtype = argv[1];
AVRMEM *mem = avr_locate_mem(p, memtype); AVRMEM *mem = avr_locate_mem(p, memtype);
if (mem == NULL) { if (mem == NULL) {
terminal_message(MSG_INFO, "%s (dump): %s memory type not defined for part %s\n", pmsg_error("(dump) %s memory type not defined for part %s\n", memtype, p->desc);
progname, memtype, p->desc);
return -1; return -1;
} }
int maxsize = mem->size; int maxsize = mem->size;
@ -242,12 +252,10 @@ static int cmd_dump(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
if (argc >= 3 && strcmp(argv[2], "...") != 0) { if (argc >= 3 && strcmp(argv[2], "...") != 0) {
addr = strtoul(argv[2], &end_ptr, 0); addr = strtoul(argv[2], &end_ptr, 0);
if (*end_ptr || (end_ptr == argv[2])) { if (*end_ptr || (end_ptr == argv[2])) {
terminal_message(MSG_INFO, "%s (dump): can't parse address %s\n", pmsg_error("(dump) cannot parse address %s\n", argv[2]);
progname, argv[2]);
return -1; return -1;
} else if (addr < 0 || addr >= maxsize) { } else if (addr < 0 || addr >= maxsize) {
terminal_message(MSG_INFO, "%s (dump): %s address 0x%05x is out of range [0, 0x%05x]\n", pmsg_error("(dump) %s address 0x%05x is out of range [0, 0x%05x]\n", mem->desc, addr, maxsize-1);
progname, mem->desc, addr, maxsize-1);
return -1; return -1;
} }
} }
@ -263,8 +271,7 @@ static int cmd_dump(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
} else if (argc == 4) { } else if (argc == 4) {
len = strtol(argv[3], &end_ptr, 0); len = strtol(argv[3], &end_ptr, 0);
if (*end_ptr || (end_ptr == argv[3])) { if (*end_ptr || (end_ptr == argv[3])) {
terminal_message(MSG_INFO, "%s (dump): can't parse length %s\n", pmsg_error("(dump) cannot parse length %s\n", argv[3]);
progname, argv[3]);
return -1; return -1;
} }
} else { } else {
@ -288,7 +295,7 @@ static int cmd_dump(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
uint8_t *buf = malloc(len); uint8_t *buf = malloc(len);
if (buf == NULL) { if (buf == NULL) {
terminal_message(MSG_INFO, "%s (dump): out of memory\n", progname); pmsg_error("(dump) out of memory\n");
return -1; return -1;
} }
@ -297,11 +304,9 @@ static int cmd_dump(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
int rc = pgm->read_byte_cached(pgm, p, mem, addr + i, &buf[i]); int rc = pgm->read_byte_cached(pgm, p, mem, addr + i, &buf[i]);
if (rc != 0) { if (rc != 0) {
report_progress(1, -1, NULL); report_progress(1, -1, NULL);
terminal_message(MSG_INFO, "%s (dump): error reading %s address 0x%05lx of part %s\n", pmsg_error("(dump) error reading %s address 0x%05lx of part %s\n", mem->desc, (long) addr + i, p->desc);
progname, mem->desc, (long) addr + i, p->desc);
if (rc == -1) if (rc == -1)
terminal_message(MSG_INFO, "%*sread operation not supported on memory type %s\n", imsg_error("%*sread operation not supported on memory type %s\n", 7, "", mem->desc);
(int) strlen(progname)+9, "", mem->desc);
return -1; return -1;
} }
report_progress(i, len, NULL); report_progress(i, len, NULL);
@ -309,7 +314,7 @@ static int cmd_dump(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
report_progress(1, 1, NULL); report_progress(1, 1, NULL);
hexdump_buf(stdout, addr, buf, len); hexdump_buf(stdout, addr, buf, len);
fprintf(stdout, "\n"); term_out("\n");
free(buf); free(buf);
@ -365,7 +370,7 @@ static int is_mantissa_only(char *p) {
static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
if (argc < 4) { if (argc < 4) {
terminal_message(MSG_INFO, msg_error(
"Usage: write <memory> <addr> <data>[,] {<data>[,]}\n" "Usage: write <memory> <addr> <data>[,] {<data>[,]}\n"
" write <memory> <addr> <len> <data>[,] {<data>[,]} ...\n" " write <memory> <addr> <len> <data>[,] {<data>[,]} ...\n"
"\n" "\n"
@ -399,14 +404,13 @@ static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
} }
int i; int i;
uint8_t write_mode; // Operation mode, "standard" or "fill" uint8_t write_mode; // Operation mode, "standard" or "fill"
uint8_t start_offset; // Which argc argument uint8_t start_offset; // Which argc argument
int len; // Number of bytes to write to memory int len; // Number of bytes to write to memory
char *memtype = argv[1]; // Memory name string char *memtype = argv[1]; // Memory name string
AVRMEM *mem = avr_locate_mem(p, memtype); AVRMEM *mem = avr_locate_mem(p, memtype);
if (mem == NULL) { if (mem == NULL) {
terminal_message(MSG_INFO, "%s (write): %s memory type not defined for part %s\n", pmsg_error("(write) %s memory type not defined for part %s\n", memtype, p->desc);
progname, memtype, p->desc);
return -1; return -1;
} }
int maxsize = mem->size; int maxsize = mem->size;
@ -414,21 +418,19 @@ static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
char *end_ptr; char *end_ptr;
int addr = strtoul(argv[2], &end_ptr, 0); int addr = strtoul(argv[2], &end_ptr, 0);
if (*end_ptr || (end_ptr == argv[2])) { if (*end_ptr || (end_ptr == argv[2])) {
terminal_message(MSG_INFO, "%s (write): can't parse address %s\n", pmsg_error("(write) cannot parse address %s\n", argv[2]);
progname, argv[2]);
return -1; return -1;
} }
if (addr < 0 || addr >= maxsize) { if (addr < 0 || addr >= maxsize) {
terminal_message(MSG_INFO, "%s (write): %s address 0x%05x is out of range [0, 0x%05x]\n", pmsg_error("(write) %s address 0x%05x is out of range [0, 0x%05x]\n", mem->desc, addr, maxsize-1);
progname, mem->desc, addr, maxsize-1);
return -1; return -1;
} }
// Allocate a buffer guaranteed to be large enough // Allocate a buffer guaranteed to be large enough
uint8_t *buf = calloc(mem->size + 8 + maxstrlen(argc-3, argv+3)+1, sizeof(uint8_t)); uint8_t *buf = calloc(mem->size + 8 + maxstrlen(argc-3, argv+3)+1, sizeof(uint8_t));
if (buf == NULL) { if (buf == NULL) {
terminal_message(MSG_INFO, "%s (write): out of memory\n", progname); pmsg_error("(write) out of memory\n");
return -1; return -1;
} }
@ -438,8 +440,7 @@ static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
start_offset = 4; start_offset = 4;
len = strtoul(argv[3], &end_ptr, 0); len = strtoul(argv[3], &end_ptr, 0);
if (*end_ptr || (end_ptr == argv[3])) { if (*end_ptr || (end_ptr == argv[3])) {
terminal_message(MSG_INFO, "%s (write ...): can't parse length %s\n", pmsg_error("(write ...) cannot parse length %s\n", argv[3]);
progname, argv[3]);
free(buf); free(buf);
return -1; return -1;
} }
@ -471,8 +472,8 @@ static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
}; };
if(sizeof(long long) != sizeof(int64_t) || (data.a[0]^data.a[7]) != 1) if(sizeof(long long) != sizeof(int64_t) || (data.a[0]^data.a[7]) != 1)
terminal_message(MSG_INFO, "%s (write): assumption on data types not met? " pmsg_error("(write) assumption on data types not met? "
"Check source and recompile\n", progname); "Check source and recompile\n");
bool is_big_endian = data.a[7]; bool is_big_endian = data.a[7];
for (i = start_offset; i < len + start_offset; i++) { for (i = start_offset; i < len + start_offset; i++) {
@ -518,7 +519,7 @@ static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
bool is_out_of_range = 0; bool is_out_of_range = 0;
int nhexdigs = p-argi-2; int nhexdigs = p-argi-2;
if(is_signed) { // Is input in range for int64_t? if(is_signed) { // Is input in range for int64_t?
errno = 0; (void) strtoll(argi, NULL, 0); errno = 0; (void) strtoll(argi, NULL, 0);
is_outside_int64_t = errno == ERANGE; is_outside_int64_t = errno == ERANGE;
} }
@ -566,9 +567,8 @@ static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
} }
if(is_outside_int64_t || is_out_of_range) if(is_outside_int64_t || is_out_of_range)
terminal_message(MSG_INFO, "%s (write): %s out of int%d_t range, " pmsg_error("(write) %s out of int%d_t range, "
"interpreted as %d-byte %lld; consider 'U' suffix\n", "interpreted as %d-byte %lld; consider 'U' suffix\n", argi, data.size*8, data.size, (long long int) data.ll);
progname, argi, data.size*8, data.size, data.ll);
} }
} }
} }
@ -583,8 +583,8 @@ static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
data.f = strtof(argi, &end_ptr); data.f = strtof(argi, &end_ptr);
if (end_ptr != argi && toupper(*end_ptr) == 'F' && end_ptr[1] == 0) if (end_ptr != argi && toupper(*end_ptr) == 'F' && end_ptr[1] == 0)
data.size = 4; data.size = 4;
if (end_ptr != argi && *end_ptr == 0) // no suffix defaults to float but ... 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) // ... do not accept valid mantissa-only floats that are integer rejects (eg, 078 or ULL overflows)
if (!is_mantissa_only(argi)) if (!is_mantissa_only(argi))
data.size = 4; data.size = 4;
} }
@ -593,29 +593,27 @@ static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
if ((*argi == '\'' && argi[arglen-1] == '\'') || (*argi == '\"' && argi[arglen-1] == '\"')) { if ((*argi == '\'' && argi[arglen-1] == '\'') || (*argi == '\"' && argi[arglen-1] == '\"')) {
char *s = calloc(arglen-1, 1); char *s = calloc(arglen-1, 1);
if (s == NULL) { if (s == NULL) {
terminal_message(MSG_INFO, "%s (write str): out of memory\n", progname); pmsg_error("(write str) out of memory\n");
free(buf); free(buf);
return -1; return -1;
} }
// Strip start and end quotes, and unescape C string // Strip start and end quotes, and unescape C string
strncpy(s, argi+1, arglen-2); strncpy(s, argi+1, arglen-2);
cfg_unescape(s, s); cfg_unescape(s, s);
if (*argi == '\'') { // Single C-style character if (*argi == '\'') { // Single C-style character
if(*s && s[1]) if(*s && s[1])
terminal_message(MSG_INFO, "%s (write): only using first character of %s\n", pmsg_error("(write) only using first character of %s\n", argi);
progname, argi);
data.ll = *s; data.ll = *s;
data.size = 1; data.size = 1;
free(s); free(s);
} else { // C-style string } else { // C-style string
data.str_ptr = s; data.str_ptr = s;
} }
} }
} }
if(!data.size && !data.str_ptr) { if(!data.size && !data.str_ptr) {
terminal_message(MSG_INFO, "%s (write): can't parse data %s\n", pmsg_error("(write) cannot parse data %s\n", argi);
progname, argi);
free(buf); free(buf);
return -1; return -1;
} }
@ -644,8 +642,8 @@ static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
data.bytes_grown = 0; data.bytes_grown = 0;
if ((addr + len + data.bytes_grown) > maxsize) { if ((addr + len + data.bytes_grown) > maxsize) {
terminal_message(MSG_INFO, "%s (write): selected address and # bytes exceed " pmsg_error("(write) selected address and # bytes exceed "
"range for %s memory\n", progname, memtype); "range for %s memory\n", memtype);
free(buf); free(buf);
return -1; return -1;
} }
@ -653,11 +651,11 @@ static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
if(data.str_ptr) if(data.str_ptr)
free(data.str_ptr); free(data.str_ptr);
terminal_message(MSG_NOTICE, "Info: writing %d bytes starting from address 0x%02lx", pmsg_notice2("(write) writing %d bytes starting from address 0x%02lx",
len + data.bytes_grown, (long) addr); len + data.bytes_grown, (long) addr);
if (write_mode == WRITE_MODE_FILL) if (write_mode == WRITE_MODE_FILL)
terminal_message(MSG_NOTICE, "; remaining space filled with %s", argv[argc - 2]); msg_notice2("; remaining space filled with %s", argv[argc - 2]);
terminal_message(MSG_NOTICE, "\n"); msg_notice2("\n");
pgm->err_led(pgm, OFF); pgm->err_led(pgm, OFF);
bool werror = false; bool werror = false;
@ -665,19 +663,16 @@ static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
for (i = 0; i < len + data.bytes_grown; i++) { for (i = 0; i < len + data.bytes_grown; i++) {
int rc = pgm->write_byte_cached(pgm, p, mem, addr+i, buf[i]); int rc = pgm->write_byte_cached(pgm, p, mem, addr+i, buf[i]);
if (rc) { if (rc) {
terminal_message(MSG_INFO, "%s (write): error writing 0x%02x at 0x%05lx, rc=%d\n", pmsg_error("(write) error writing 0x%02x at 0x%05lx, rc=%d\n", buf[i], (long) addr+i, (int) rc);
progname, buf[i], (long) addr+i, (int) rc);
if (rc == -1) if (rc == -1)
terminal_message(MSG_INFO, "%*swrite operation not supported on memory type %s\n", imsg_error("%*swrite operation not supported on memory type %s\n", 8, "", mem->desc);
(int) strlen(progname)+10, "", mem->desc);
werror = true; werror = true;
} }
uint8_t b; uint8_t b;
rc = pgm->read_byte_cached(pgm, p, mem, addr+i, &b); rc = pgm->read_byte_cached(pgm, p, mem, addr+i, &b);
if (b != buf[i]) { if (b != buf[i]) {
terminal_message(MSG_INFO, "%s (write): error writing 0x%02x at 0x%05lx cell=0x%02x\n", pmsg_error("(write) error writing 0x%02x at 0x%05lx cell=0x%02x\n", buf[i], (long) addr+i, b);
progname, buf[i], (long) addr+i, b);
werror = true; werror = true;
} }
@ -713,14 +708,13 @@ static int cmd_send(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
int len; int len;
if (spi_mode && (pgm->spi == NULL)) { if (spi_mode && (pgm->spi == NULL)) {
terminal_message(MSG_INFO, "%s (send): the %s programmer does not support direct SPI transfers\n", pmsg_error("(send) the %s programmer does not support direct SPI transfers\n", pgm->type);
progname, pgm->type);
return -1; return -1;
} }
if ((argc > 5) || ((argc < 5) && (!spi_mode))) { if ((argc > 5) || ((argc < 5) && (!spi_mode))) {
terminal_message(MSG_INFO, spi_mode? msg_error(spi_mode?
"Usage: send <byte1> [<byte2> [<byte3> [<byte4>]]]\n": "Usage: send <byte1> [<byte2> [<byte3> [<byte4>]]]\n":
"Usage: send <byte1> <byte2> <byte3> <byte4>\n"); "Usage: send <byte1> <byte2> <byte3> <byte4>\n");
return -1; return -1;
@ -733,8 +727,7 @@ static int cmd_send(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
for (i=1; i<argc; i++) { for (i=1; i<argc; i++) {
cmd[i-1] = strtoul(argv[i], &e, 0); cmd[i-1] = strtoul(argv[i], &e, 0);
if (*e || (e == argv[i])) { if (*e || (e == argv[i])) {
terminal_message(MSG_INFO, "%s (send): can't parse byte %s\n", pmsg_error("(send) cannot parse byte %s\n", argv[i]);
progname, argv[i]);
return -1; return -1;
} }
} }
@ -749,19 +742,17 @@ static int cmd_send(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
/* /*
* display results * display results
*/ */
terminal_message(MSG_INFO, "results:"); term_out("results:");
for (i=0; i<len; i++) for (i=0; i<len; i++)
terminal_message(MSG_INFO, " %02x", res[i]); term_out(" %02x", res[i]);
terminal_message(MSG_INFO, "\n"); term_out("\n\n");
fprintf(stdout, "\n");
return 0; return 0;
} }
static int cmd_erase(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { static int cmd_erase(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
terminal_message(MSG_INFO, "%s: erasing chip\n", progname); term_out("erasing chip ...\n");
// Erase chip and clear cache // Erase chip and clear cache
pgm->chip_erase_cached(pgm, p); pgm->chip_erase_cached(pgm, p);
@ -771,20 +762,18 @@ 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_pgerase(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
if(argc < 3) { if(argc < 3) {
terminal_message(MSG_INFO, "Usage: pgerase <memory> <addr>\n"); msg_error("Usage: pgerase <memory> <addr>\n");
return -1; return -1;
} }
char *memtype = argv[1]; char *memtype = argv[1];
AVRMEM *mem = avr_locate_mem(p, memtype); AVRMEM *mem = avr_locate_mem(p, memtype);
if(!mem) { if(!mem) {
terminal_message(MSG_INFO, "%s (pgerase): %s memory type not defined for part %s\n", pmsg_error("(pgerase) %s memory type not defined for part %s\n", memtype, p->desc);
progname, memtype, p->desc);
return -1; return -1;
} }
if(!avr_has_paged_access(pgm, mem)) { if(!avr_has_paged_access(pgm, mem)) {
terminal_message(MSG_INFO, "%s (pgerase): %s memory cannot be paged addressed by %s\n", pmsg_error("(pgerase) %s memory cannot be paged addressed by %s\n", memtype, (char *) ldata(lfirst(pgm->id)));
progname, memtype, ldata(lfirst(pgm->id)));
return -1; return -1;
} }
@ -793,21 +782,17 @@ static int cmd_pgerase(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
char *end_ptr; char *end_ptr;
int addr = strtoul(argv[2], &end_ptr, 0); int addr = strtoul(argv[2], &end_ptr, 0);
if(*end_ptr || (end_ptr == argv[2])) { if(*end_ptr || (end_ptr == argv[2])) {
terminal_message(MSG_INFO, "%s (pgerase): can't parse address %s\n", pmsg_error("(pgerase) cannot parse address %s\n", argv[2]);
progname, argv[2]);
return -1; return -1;
} }
if (addr < 0 || addr >= maxsize) { if (addr < 0 || addr >= maxsize) {
terminal_message(MSG_INFO, "%s (pgerase): %s address 0x%05x is out of range [0, 0x%05x]\n", pmsg_error("(pgerase) %s address 0x%05x is out of range [0, 0x%05x]\n", mem->desc, addr, maxsize-1);
progname, mem->desc, addr, maxsize-1);
return -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) { if(pgm->page_erase_cached(pgm, p, mem, (unsigned int) addr) < 0) {
terminal_message(MSG_INFO, "%s (pgerase): unable to erase %s page at 0x%05x\n", pmsg_error("(pgerase) unable to erase %s page at 0x%05x\n", mem->desc, addr);
progname, mem->desc, addr);
return -1; return -1;
} }
@ -816,9 +801,9 @@ static int cmd_pgerase(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
static int cmd_part(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { static int cmd_part(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
fprintf(stdout, "\n"); term_out("\n");
avr_display(stdout, p, "", 0); avr_display(stdout, p, "", 0);
fprintf(stdout, "\n"); term_out("\n");
return 0; return 0;
} }
@ -831,20 +816,18 @@ static int cmd_sig(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
rc = avr_signature(pgm, p); rc = avr_signature(pgm, p);
if (rc != 0) { if (rc != 0) {
terminal_message(MSG_INFO, "%s (sig): error reading signature data, rc=%d\n", pmsg_error("(sig) error reading signature data, rc=%d\n", rc);
progname, rc);
} }
m = avr_locate_mem(p, "signature"); m = avr_locate_mem(p, "signature");
if (m == NULL) { if (m == NULL) {
terminal_message(MSG_INFO, "%s (sig): signature data not defined for device %s\n", pmsg_error("(sig) signature data not defined for device %s\n", p->desc);
progname, p->desc);
} }
else { else {
fprintf(stdout, "Device signature = 0x"); term_out("Device signature = 0x");
for (i=0; i<m->size; i++) for (i=0; i<m->size; i++)
fprintf(stdout, "%02x", m->buf[i]); term_out("%02x", m->buf[i]);
fprintf(stdout, "\n\n"); term_out("\n\n");
} }
return 0; return 0;
@ -861,8 +844,8 @@ static int cmd_quit(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
static int cmd_parms(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { static int cmd_parms(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
pgm->print_parms(pgm); pgm->print_parms(pgm, stdout);
terminal_message(MSG_INFO, "\n"); term_out("\n");
return 0; return 0;
} }
@ -873,18 +856,16 @@ static int cmd_vtarg(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
char *endp; char *endp;
if (argc != 2) { if (argc != 2) {
terminal_message(MSG_INFO, "Usage: vtarg <value>\n"); msg_error("Usage: vtarg <value>\n");
return -1; return -1;
} }
v = strtod(argv[1], &endp); v = strtod(argv[1], &endp);
if (endp == argv[1]) { if (endp == argv[1]) {
terminal_message(MSG_INFO, "%s (vtarg): can't parse voltage %s\n", pmsg_error("(vtarg) cannot parse voltage %s\n", argv[1]);
progname, argv[1]);
return -1; return -1;
} }
if ((rc = pgm->set_vtarget(pgm, v)) != 0) { if ((rc = pgm->set_vtarget(pgm, v)) != 0) {
terminal_message(MSG_INFO, "%s (vtarg): unable to set V[target] (rc = %d)\n", pmsg_error("(vtarg) unable to set V[target] (rc = %d)\n", rc);
progname, rc);
return -3; return -3;
} }
return 0; return 0;
@ -897,7 +878,7 @@ static int cmd_fosc(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
char *endp; char *endp;
if (argc != 2) { if (argc != 2) {
terminal_message(MSG_INFO, "Usage: fosc <value>[M|k] | off\n"); msg_error("Usage: fosc <value>[M|k] | off\n");
return -1; return -1;
} }
v = strtod(argv[1], &endp); v = strtod(argv[1], &endp);
@ -905,8 +886,7 @@ static int cmd_fosc(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
if (strcmp(argv[1], "off") == 0) if (strcmp(argv[1], "off") == 0)
v = 0.0; v = 0.0;
else { else {
terminal_message(MSG_INFO, "%s (fosc): can't parse frequency %s\n", pmsg_error("(fosc) cannot parse frequency %s\n", argv[1]);
progname, argv[1]);
return -1; return -1;
} }
} }
@ -915,8 +895,7 @@ static int cmd_fosc(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
else if (*endp == 'k' || *endp == 'K') else if (*endp == 'k' || *endp == 'K')
v *= 1e3; v *= 1e3;
if ((rc = pgm->set_fosc(pgm, v)) != 0) { if ((rc = pgm->set_fosc(pgm, v)) != 0) {
terminal_message(MSG_INFO, "%s (fosc): unable to set oscillator frequency (rc = %d)\n", pmsg_error("(fosc) unable to set oscillator frequency (rc = %d)\n", rc);
progname, rc);
return -3; return -3;
} }
return 0; return 0;
@ -929,19 +908,17 @@ static int cmd_sck(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
char *endp; char *endp;
if (argc != 2) { if (argc != 2) {
terminal_message(MSG_INFO, "Usage: sck <value>\n"); msg_error("Usage: sck <value>\n");
return -1; return -1;
} }
v = strtod(argv[1], &endp); v = strtod(argv[1], &endp);
if (endp == argv[1]) { if (endp == argv[1]) {
terminal_message(MSG_INFO, "%s (sck): can't parse period %s\n", pmsg_error("(sck) cannot parse period %s\n", argv[1]);
progname, argv[1]);
return -1; return -1;
} }
v *= 1e-6; /* Convert from microseconds to seconds. */ v *= 1e-6; // Convert from microseconds to seconds
if ((rc = pgm->set_sck_period(pgm, v)) != 0) { if ((rc = pgm->set_sck_period(pgm, v)) != 0) {
terminal_message(MSG_INFO, "%s (sck): unable to set SCK period (rc = %d)\n", pmsg_error("(sck) unable to set SCK period (rc = %d)\n", rc);
progname, rc);
return -3; return -3;
} }
return 0; return 0;
@ -955,34 +932,30 @@ static int cmd_varef(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
char *endp; char *endp;
if (argc != 2 && argc != 3) { if (argc != 2 && argc != 3) {
terminal_message(MSG_INFO, "Usage: varef [channel] <value>\n"); msg_error("Usage: varef [channel] <value>\n");
return -1; return -1;
} }
if (argc == 2) { if (argc == 2) {
chan = 0; chan = 0;
v = strtod(argv[1], &endp); v = strtod(argv[1], &endp);
if (endp == argv[1]) { if (endp == argv[1]) {
terminal_message(MSG_INFO, "%s (varef): can't parse voltage %s\n", pmsg_error("(varef) cannot parse voltage %s\n", argv[1]);
progname, argv[1]);
return -1; return -1;
} }
} else { } else {
chan = strtoul(argv[1], &endp, 10); chan = strtoul(argv[1], &endp, 10);
if (endp == argv[1]) { if (endp == argv[1]) {
terminal_message(MSG_INFO, "%s (varef): can't parse channel %s\n", pmsg_error("(varef) cannot parse channel %s\n", argv[1]);
progname, argv[1]);
return -1; return -1;
} }
v = strtod(argv[2], &endp); v = strtod(argv[2], &endp);
if (endp == argv[2]) { if (endp == argv[2]) {
terminal_message(MSG_INFO, "%s (varef): can't parse voltage %s\n", pmsg_error("(varef) cannot parse voltage %s\n", argv[2]);
progname, argv[2]);
return -1; return -1;
} }
} }
if ((rc = pgm->set_varef(pgm, chan, v)) != 0) { if ((rc = pgm->set_varef(pgm, chan, v)) != 0) {
terminal_message(MSG_INFO, "%s (varef): unable to set V[aref] (rc = %d)\n", pmsg_error("(varef) unable to set V[aref] (rc = %d)\n", rc);
progname, rc);
return -3; return -3;
} }
return 0; return 0;
@ -992,19 +965,19 @@ static int cmd_varef(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
static int cmd_help(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { static int cmd_help(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
int i; int i;
fprintf(stdout, "Valid commands:\n"); term_out("Valid commands:\n");
for (i=0; i<NCMDS; i++) { for (i=0; i<NCMDS; i++) {
if(!*(void (**)(void)) ((char *) pgm + cmd[i].fnoff)) if(!*(void (**)(void)) ((char *) pgm + cmd[i].fnoff))
continue; continue;
fprintf(stdout, " %-7s : ", cmd[i].name); term_out(" %-7s : ", cmd[i].name);
fprintf(stdout, cmd[i].desc, cmd[i].name); term_out(cmd[i].desc, cmd[i].name);
fprintf(stdout, "\n"); term_out("\n");
} }
fprintf(stdout, "\n" term_out("\n"
"Note that not all programmer derivatives support all commands. Flash and\n" "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" "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" "read and write access; the cache is synchronised on quit or flush commands.\n"
"command to display valid memory types for use with dump and write.\n\n"); "The part command displays valid memory types for use with dump and write.\n\n");
return 0; return 0;
} }
@ -1026,26 +999,24 @@ static int cmd_verbose(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
char *endp; char *endp;
if (argc != 1 && argc != 2) { if (argc != 1 && argc != 2) {
terminal_message(MSG_INFO, "Usage: verbose [<value>]\n"); msg_error("Usage: verbose [<value>]\n");
return -1; return -1;
} }
if (argc == 1) { if (argc == 1) {
terminal_message(MSG_INFO, "Verbosity level: %d\n", verbose); msg_error("Verbosity level: %d\n", verbose);
return 0; return 0;
} }
nverb = strtol(argv[1], &endp, 0); nverb = strtol(argv[1], &endp, 0);
if (endp == argv[1] || *endp) { if (endp == argv[1] || *endp) {
terminal_message(MSG_INFO, "%s (verbose): can't parse verbosity level %s\n", pmsg_error("(verbose) cannot parse verbosity level %s\n", argv[1]);
progname, argv[1]);
return -1; return -1;
} }
if (nverb < 0) { if (nverb < 0) {
terminal_message(MSG_INFO, "%s: verbosity level must not be negative: %d\n", pmsg_error("(verbose) level must not be negative: %d\n", nverb);
progname, nverb);
return -1; return -1;
} }
verbose = nverb; verbose = nverb;
terminal_message(MSG_INFO, "New verbosity level: %d\n", verbose); term_out("New verbosity level: %d\n", verbose);
return 0; return 0;
} }
@ -1055,26 +1026,24 @@ static int cmd_quell(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
char *endp; char *endp;
if (argc != 1 && argc != 2) { if (argc != 1 && argc != 2) {
terminal_message(MSG_INFO, "Usage: quell [<value>]\n"); msg_error("Usage: quell [<value>]\n");
return -1; return -1;
} }
if (argc == 1) { if (argc == 1) {
terminal_message(MSG_INFO, "Quell level: %d\n", quell_progress); msg_error("Quell level: %d\n", quell_progress);
return 0; return 0;
} }
nquell = strtol(argv[1], &endp, 0); nquell = strtol(argv[1], &endp, 0);
if (endp == argv[1] || *endp) { if (endp == argv[1] || *endp) {
terminal_message(MSG_INFO, "%s (quell): can't parse quell level %s\n", pmsg_error("(quell) cannot parse quell level %s\n", argv[1]);
progname, argv[1]);
return -1; return -1;
} }
if (nquell < 0) { if (nquell < 0) {
terminal_message(MSG_INFO, "%s: quell level must not be negative: %d\n", pmsg_error("(quell) level must not be negative: %d\n", nquell);
progname, nquell);
return -1; return -1;
} }
quell_progress = nquell; quell_progress = nquell;
terminal_message(MSG_INFO, "New quell level: %d\n", quell_progress); term_out("New quell level: %d\n", quell_progress);
if(quell_progress > 0) if(quell_progress > 0)
update_progress = NULL; update_progress = NULL;
@ -1195,8 +1164,7 @@ static int do_cmd(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
return cmd[i].func(pgm, p, argc, argv); return cmd[i].func(pgm, p, argc, argv);
if (len && strncasecmp(argv[0], cmd[i].name, len)==0) { if (len && strncasecmp(argv[0], cmd[i].name, len)==0) {
if (hold != -1) { if (hold != -1) {
terminal_message(MSG_INFO, "%s (cmd): command %s is ambiguous\n", pmsg_error("(cmd) command %s is ambiguous\n", argv[0]);
progname, argv[0]);
return -1; return -1;
} }
hold = i; hold = i;
@ -1206,104 +1174,177 @@ static int do_cmd(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
if (hold != -1) if (hold != -1)
return cmd[hold].func(pgm, p, argc, argv); return cmd[hold].func(pgm, p, argc, argv);
terminal_message(MSG_INFO, "%s (cmd): invalid command %s\n", pmsg_error("(cmd) invalid command %s\n", argv[0]);
progname, argv[0]);
return -1; return -1;
} }
char *terminal_get_input(const char *prompt) { char *terminal_get_input(const char *prompt) {
#if defined(HAVE_LIBREADLINE) && !defined(WIN32)
char *input;
input = readline(prompt);
if ((input != NULL) && (strlen(input) >= 1))
add_history(input);
return input;
#else
char input[256]; char input[256];
fprintf(stdout, "%s", prompt);
if (fgets(input, sizeof(input), stdin)) term_out("%s", prompt);
{ if(fgets(input, sizeof(input), stdin)) {
/* FIXME: readline strips the '\n', should this too? */ int len = strlen(input);
return strdup(input); if(len > 0 && input[len-1] == '\n')
input[len-1] = 0;
return cfg_strdup(__func__, input);
} }
else
return NULL; return NULL;
#endif
} }
int terminal_mode(PROGRAMMER *pgm, AVRPART *p) { static int process_line(char *cmdbuf, PROGRAMMER *pgm, struct avrpart *p) {
char *cmdbuf; int argc, rc;
char *q; char **argv = NULL, *q;
int rc;
int argc;
char **argv;
rc = 0; // Find the start of the command, skipping any white space
while ((cmdbuf = terminal_get_input("avrdude> ")) != NULL) { q = cmdbuf;
/* while(*q && isspace((unsigned char) *q))
* find the start of the command, skipping any white space q++;
*/
q = cmdbuf;
while (*q && isspace((unsigned char) *q))
q++;
/* skip blank lines and comments */ // Skip blank lines and comments
if (!*q || (*q == '#')) if (!*q || (*q == '#'))
continue; return 0;
/* tokenize command line */ // Tokenize command line
argc = tokenize(q, &argv); argc = tokenize(q, &argv);
if (argc < 0) {
free(cmdbuf); if(!argv)
return argc; return -1;
}
#if !defined(HAVE_LIBREADLINE) || defined(WIN32) || defined(__APPLE__) #if !defined(HAVE_LIBREADLINE) || defined(WIN32) || defined(__APPLE__)
fprintf(stdout, ">>> "); term_out(">>> ");
for (int i=0; i<argc; i++) for (int i=0; i<argc; i++)
fprintf(stdout, "%s ", argv[i]); term_out("%s ", argv[i]);
fprintf(stdout, "\n"); term_out("\n");
#endif #endif
/* run the command */ // Run the command
rc = do_cmd(pgm, p, argc, argv); rc = do_cmd(pgm, p, argc, argv);
free(argv); free(argv);
if (rc > 0) {
rc = 0; return rc;
break; }
#if defined(HAVE_LIBREADLINE)
static PROGRAMMER *term_pgm;
static struct avrpart *term_p;
static int term_running;
// Any character in standard input available (without sleeping)?
static int readytoread() {
#ifdef WIN32
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
while(1) {
INPUT_RECORD input[1] = { 0 };
DWORD dwNumberOfEventsRead = 0;
if(!PeekConsoleInputA(hStdin, input, ARRAYSIZE(input), &dwNumberOfEventsRead)) {
DWORD dwError = GetLastError();
// Stdin redirected from a pipe or file (FIXME: reading from a pipe may sleep)
if(dwError == ERROR_INVALID_HANDLE)
return 1;
pmsg_warning("PeekConsoleInputA() failed with error code %u\n", (unsigned int) dwError);
return -1;
}
if(dwNumberOfEventsRead <= 0) // Nothing in the input buffer
return 0;
// Filter out all the events that readline does not handle ...
if((input[0].EventType & KEY_EVENT) != 0 && input[0].Event.KeyEvent.bKeyDown)
return 1;
// Drain other events not handled by readline
if(!ReadConsoleInputA(hStdin, input, ARRAYSIZE(input), &dwNumberOfEventsRead)) {
pmsg_warning("ReadConsoleInputA() failed with error code %u\n", (unsigned int) GetLastError());
return -1;
} }
free(cmdbuf);
} }
#else
struct timeval tv = { 0L, 0L };
fd_set fds;
FD_ZERO(&fds);
FD_SET(0, &fds);
pgm->flush_cache(pgm, p); return select(1, &fds, NULL, NULL, &tv) > 0;
#endif
}
return rc; // Callback processes commands whenever readline() has finished
void term_gotline(char *cmdstr) {
if(cmdstr) {
if(*cmdstr) {
add_history(cmdstr);
// only quit/abort returns a value > 0
if(process_line(cmdstr, term_pgm, term_p) > 0)
term_running = 0;
}
free(cmdstr);
} else {
// call quit at end of file or terminal ^D
term_out("\n");
cmd_quit(term_pgm, term_p, 0, NULL);
term_running = 0;
}
} }
int terminal_message(const int msglvl, const char *format, ...) { int terminal_mode(PROGRAMMER *pgm, struct avrpart *p) {
term_pgm = pgm; // For callback routine
term_p = p;
rl_callback_handler_install("avrdude> ", term_gotline);
term_running = 1;
for(int n=1; term_running; n++) {
if(n%16 == 0) { // Every 100 ms (16*6.25 us) reset bootloader watchdog timer
if(pgm->term_keep_alive)
pgm->term_keep_alive(pgm, NULL);
}
usleep(6250);
if(readytoread() > 0 && term_running)
rl_callback_read_char();
}
rl_callback_handler_remove();
return pgm->flush_cache(pgm, p);
}
#else
int terminal_mode(PROGRAMMER *pgm, struct avrpart *p) {
char *cmdbuf;
int rc = 0; int rc = 0;
va_list ap;
fflush(stdout); fflush(stderr); while((cmdbuf = terminal_get_input("avrdude> "))) {
if (verbose >= msglvl) { int rc = process_line(cmdbuf, pgm, p);
va_start(ap, format); free(cmdbuf);
rc = vfprintf(stderr, format, ap); if(rc > 0)
va_end(ap); break;
} }
fflush(stderr);
return rc; if(rc <= 0)
cmd_quit(pgm, p, 0, NULL);
return pgm->flush_cache(pgm, p);
} }
#endif
static void update_progress_tty(int percent, double etime, const char *hdr, int finish) { static void update_progress_tty(int percent, double etime, const char *hdr, int finish) {
static char *header; static char *header;
static int last, done; static int last, done = 1;
int i; int i;
setvbuf(stderr, (char *) NULL, _IONBF, 0); setvbuf(stderr, (char *) NULL, _IONBF, 0);
@ -1330,7 +1371,7 @@ static void update_progress_tty(int percent, double etime, const char *hdr, int
hashes[i/2] = '#'; hashes[i/2] = '#';
hashes[50] = 0; hashes[50] = 0;
msg_info("\r%s | %s | %d%% %0.2fs", header, hashes, showperc, etime); msg_info("\r%s | %s | %d%% %0.2f s ", header, hashes, showperc, etime);
if(percent == 100) { if(percent == 100) {
if(finish) if(finish)
msg_info("\n\n"); msg_info("\n\n");
@ -1343,7 +1384,7 @@ static void update_progress_tty(int percent, double etime, const char *hdr, int
} }
static void update_progress_no_tty(int percent, double etime, const char *hdr, int finish) { static void update_progress_no_tty(int percent, double etime, const char *hdr, int finish) {
static int last, done; static int last, done = 1;
setvbuf(stderr, (char *) NULL, _IONBF, 0); setvbuf(stderr, (char *) NULL, _IONBF, 0);

View File

@ -35,7 +35,6 @@ typedef enum {
int terminal_mode(PROGRAMMER * pgm, struct avrpart * p); int terminal_mode(PROGRAMMER * pgm, struct avrpart * p);
char * terminal_get_input(const char *prompt); char * terminal_get_input(const char *prompt);
void terminal_setup_update_progress(); void terminal_setup_update_progress();
int terminal_message(const int msglvl, const char *format, ...);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -335,11 +335,11 @@ int update_is_readable(const char *fn) {
static void ioerror(const char *iotype, UPDATE *upd) { static void ioerror(const char *iotype, UPDATE *upd) {
int errnocp = errno; int errnocp = errno;
pmsg_ext_error("file %s is not %s", update_outname(upd->filename), iotype); pmsg_ext_error("file %s is not %s: ", update_outname(upd->filename), iotype);
if(errnocp) if(errnocp)
msg_ext_error("memstats(): %s", strerror(errnocp)); msg_ext_error("%s", strerror(errnocp));
else if(upd->filename && *upd->filename) else if(upd->filename && *upd->filename)
msg_ext_error(" (not a regular or character file?)"); msg_ext_error("(not a regular or character file?)");
msg_ext_error("\n"); msg_ext_error("\n");
} }
@ -456,7 +456,8 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
} }
pmsg_info("reading %s%s memory ...\n", mem->desc, alias_mem_desc); pmsg_info("reading %s%s memory ...\n", mem->desc, alias_mem_desc);
report_progress(0, 1, "Reading"); if(mem->size > 32 || verbose > 1)
report_progress(0, 1, "Reading");
rc = avr_read(pgm, p, upd->memtype, 0); rc = avr_read(pgm, p, upd->memtype, 0);
report_progress(1, 1, NULL); report_progress(1, 1, NULL);
@ -511,7 +512,8 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
update_plural(fs.nbytes), mem->desc, alias_mem_desc); update_plural(fs.nbytes), mem->desc, alias_mem_desc);
if (!(flags & UF_NOWRITE)) { if (!(flags & UF_NOWRITE)) {
report_progress(0, 1, "Writing"); if(mem->size > 32 || verbose > 1)
report_progress(0, 1, "Writing");
rc = avr_write(pgm, p, upd->memtype, size, (flags & UF_AUTO_ERASE) != 0); rc = avr_write(pgm, p, upd->memtype, size, (flags & UF_AUTO_ERASE) != 0);
report_progress(1, 1, NULL); report_progress(1, 1, NULL);
} else { } else {
@ -569,7 +571,8 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
pmsg_notice2("reading on-chip %s%s data ...\n", mem->desc, alias_mem_desc); pmsg_notice2("reading on-chip %s%s data ...\n", mem->desc, alias_mem_desc);
} }
report_progress (0,1,"Reading"); if(mem->size > 32 || verbose > 1)
report_progress (0,1,"Reading");
rc = avr_read(pgm, p, upd->memtype, v); rc = avr_read(pgm, p, upd->memtype, v);
report_progress (1,1,NULL); report_progress (1,1,NULL);
if (rc < 0) { if (rc < 0) {