Merge branch 'avrdudes:main' into Xplained_Pro_PDI
This commit is contained in:
commit
f2a413d2dc
|
@ -49,6 +49,7 @@ jobs:
|
|||
libusb-1.0-0-dev
|
||||
libhidapi-dev
|
||||
libftdi1-dev
|
||||
libreadline-dev
|
||||
texinfo
|
||||
texlive
|
||||
texi2html
|
||||
|
@ -110,6 +111,7 @@ jobs:
|
|||
libusb-1.0-0-dev:${{matrix.arch}}
|
||||
libhidapi-dev:${{matrix.arch}}
|
||||
libftdi1-dev:${{matrix.arch}}
|
||||
libreadline-dev:${{matrix.arch}}
|
||||
- name: Configure
|
||||
run: >-
|
||||
cmake
|
||||
|
|
16
NEWS
16
NEWS
|
@ -58,6 +58,12 @@ Changes since version 7.0:
|
|||
- Make UPDI programmers less verbose during initialization
|
||||
#1084
|
||||
- Quell mode isn't handled systematically #1114
|
||||
- Mixing the progress bar with warning messages #1136
|
||||
- Inconsistent terminal output re stdout and stderr #1130
|
||||
- Supress the warning for Microchip SNAP #1135
|
||||
- ATtiny85 communication problem with default bitclock #1133
|
||||
- [Regression] Optiboot for "modern AVRs" no longer works #1120
|
||||
- Cannot access EEPROM on some bootloader/part combos #970
|
||||
|
||||
* Pull requests:
|
||||
|
||||
|
@ -153,6 +159,16 @@ Changes since version 7.0:
|
|||
- Suppress Teensy USB communication error message on reboot #1122
|
||||
- Fix UPDI erase when target is locked #1125
|
||||
- Review and overhaul AVRDUDE's messaging system #1126
|
||||
- Look for ~/.config/avrdude/avrdude.rc then ~/.avrduderc #1131
|
||||
- Revamp terminal output (progress bar, callback and
|
||||
stdout/stderr) #1132
|
||||
- Detect PICkit4 and SNAP in PIC mode #1138
|
||||
- Mention -B in the error message #1139
|
||||
- Support optiboot, optiboot_dx and optiboot_x bootloaders for
|
||||
-c arduino #1140
|
||||
- Always use paged access for programmers that serve
|
||||
bootloaders #1141
|
||||
- Add libreadline-dev for Linux github action build #1146
|
||||
|
||||
* Internals:
|
||||
|
||||
|
|
4
build.sh
4
build.sh
|
@ -53,9 +53,9 @@ case "${ostype}" in
|
|||
# Apple M1 (may be new version of homebrew also)
|
||||
if [ -d /opt/homebrew ]
|
||||
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
|
||||
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
|
||||
;;
|
||||
|
|
14
src/avr.c
14
src/avr.c
|
@ -377,8 +377,9 @@ int avr_read_mem(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, con
|
|||
return avr_mem_hiaddr(mem);
|
||||
}
|
||||
|
||||
if (pgm->paged_load != NULL && mem->page_size > 1 &&
|
||||
mem->size % mem->page_size == 0) {
|
||||
// HW programmers need a page size > 1, bootloader typ only offer paged r/w
|
||||
if ((pgm->paged_load && mem->page_size > 1 && mem->size % mem->page_size == 0) ||
|
||||
((pgm->prog_modes & PM_SPM) && avr_has_paged_access(pgm, mem))) {
|
||||
/*
|
||||
* the programmer supports a paged mode read
|
||||
*/
|
||||
|
@ -894,7 +895,9 @@ int avr_write_mem(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m, int
|
|||
return i;
|
||||
}
|
||||
|
||||
if (pgm->paged_write != NULL && m->page_size > 1) {
|
||||
// HW programmers need a page size > 1, bootloader typ only offer paged r/w
|
||||
if ((pgm->paged_load && m->page_size > 1 && m->size % m->page_size == 0) ||
|
||||
((pgm->prog_modes & PM_SPM) && avr_has_paged_access(pgm, m))) {
|
||||
/*
|
||||
* the programmer supports a paged mode write
|
||||
*/
|
||||
|
@ -1036,13 +1039,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 rc;
|
||||
|
||||
report_progress (0,1,"Reading");
|
||||
if(verbose > 1)
|
||||
report_progress(0, 1, "Reading");
|
||||
rc = avr_read(pgm, p, "signature", 0);
|
||||
if (rc < LIBAVRDUDE_SUCCESS) {
|
||||
pmsg_error("unable to read signature data for part %s, rc=%d\n", p->desc, rc);
|
||||
return rc;
|
||||
}
|
||||
report_progress (1,1,NULL);
|
||||
report_progress(1, 1, NULL);
|
||||
|
||||
return LIBAVRDUDE_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
* - 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);
|
||||
|
||||
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);
|
||||
if((rc = pgm->paged_load(pgm, p, mem, pgsize, base, pgsize)) >= 0)
|
||||
memcpy(buf, mem->buf + base, pgsize);
|
||||
memcpy(mem->buf + base, pagecopy, pgsize);
|
||||
|
||||
if(rc < 0) {
|
||||
if(rc < 0 && pgm->read_byte != avr_read_byte_cached) {
|
||||
rc = LIBAVRDUDE_SUCCESS;
|
||||
for(int i=0; i<pgsize; i++) {
|
||||
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);
|
||||
|
||||
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(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) {
|
||||
// Write modified page cont to device; if unsuccessful try bytewise access
|
||||
if(avr_write_page_default(pgm, p, mem, base, cp->cont + base) < 0) {
|
||||
for(int i=0; i < cp->page_size; i++)
|
||||
if(cp->cont[base+i] != cp->copy[base+i])
|
||||
if(pgm->write_byte(pgm, p, mem, base+i, cp->cont[base+i]) < 0 ||
|
||||
pgm->read_byte(pgm, p, mem, base+i, cp->copy+base+i) < 0) {
|
||||
report_progress(1, -1, NULL);
|
||||
if(nlOnErr && quell_progress)
|
||||
msg_info("\n");
|
||||
pmsg_error("writeCachePage() %s access error at addr 0x%04x\n", mem->desc, base+i);
|
||||
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||
}
|
||||
if(pgm->read_byte != avr_read_byte_cached && pgm->write_byte != avr_write_byte_cached) {
|
||||
for(int i=0; i < cp->page_size; i++)
|
||||
if(cp->cont[base+i] != cp->copy[base+i])
|
||||
if(pgm->write_byte(pgm, p, mem, base+i, cp->cont[base+i]) < 0 ||
|
||||
pgm->read_byte(pgm, p, mem, base+i, cp->copy+base+i) < 0) {
|
||||
report_progress(1, -1, NULL);
|
||||
if(nlOnErr && quell_progress)
|
||||
msg_info("\n");
|
||||
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
|
||||
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
|
||||
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(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,
|
||||
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))
|
||||
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(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;
|
||||
|
||||
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;
|
||||
} else {
|
||||
if(!pgm->page_erase || pgm->page_erase(pgm, p, mem, uaddr) < 0)
|
||||
|
|
|
@ -332,18 +332,20 @@ programmed in high-voltage serial mode.
|
|||
Override the RS-232 connection baud rate specified in the respective
|
||||
programmer's entry of the configuration file.
|
||||
.It Fl B Ar bitclock
|
||||
Specify the bit clock period for the JTAG interface or the ISP clock (JTAG ICE only).
|
||||
The value is a floating-point number in microseconds.
|
||||
Alternatively, the value might be suffixed with "Hz", "kHz", or "MHz",
|
||||
in order to specify the bit clock frequency, rather than a period.
|
||||
The default value of the JTAG ICE results in about 1 microsecond bit
|
||||
clock period, suitable for target MCUs running at 4 MHz clock and
|
||||
above.
|
||||
Unlike certain parameters in the STK500, the JTAG ICE resets all its
|
||||
parameters to default values when the programming software signs
|
||||
off from the ICE, so for MCUs running at lower clock speeds, this
|
||||
parameter must be specified on the command-line.
|
||||
Specify the bit clock period for the JTAG, PDI, TPI, UPDI, or ISP
|
||||
interface. The value is a floating-point number in microseconds.
|
||||
Alternatively, the value might be suffixed with "Hz", "kHz" or
|
||||
"MHz" in order to specify the bit clock frequency rather than a
|
||||
period. Some programmers default their bit clock value to a 1
|
||||
microsecond bit clock period, suitable for target MCUs running at 4
|
||||
MHz clock and above. Slower MCUs need a correspondingly higher bit
|
||||
clock period. Some programmers reset their bit clock value to the
|
||||
default value when the programming software signs off, whilst others
|
||||
store the last used bit clock value. It is recommended to always
|
||||
specify the bit clock if read/write speed is important.
|
||||
You can use the 'default_bitclock' keyword in your
|
||||
.Pa ${HOME}/.config/avrdude/avrdude.rc
|
||||
or
|
||||
.Pa ${HOME}/.avrduderc
|
||||
file to assign a default value to keep from having to specify this
|
||||
option on every invocation.
|
||||
|
@ -357,6 +359,8 @@ through the use of a config file to make
|
|||
work with different programmers as long as the programmer supports the
|
||||
Atmel AVR serial program method. You can use the 'default_programmer'
|
||||
keyword in your
|
||||
.Pa ${HOME}/.config/avrdude/avrdude.rc
|
||||
or
|
||||
.Pa ${HOME}/.avrduderc
|
||||
file to assign a default programmer to keep from having to specify
|
||||
this option on every invocation.
|
||||
|
@ -507,6 +511,8 @@ actual connection to a target controller), this option can be used
|
|||
together with
|
||||
.Fl t
|
||||
to continue in terminal mode.
|
||||
Moreover, the option allows to continue despite failed initialization
|
||||
of connection between a programmer and a target.
|
||||
.It Fl i Ar delay
|
||||
For bitbang-type programmers, delay for approximately
|
||||
.Ar delay
|
||||
|
@ -1320,10 +1326,10 @@ the CS line being managed outside the application.
|
|||
.Sh FILES
|
||||
.Bl -tag -offset indent -width /dev/ppi0XXX
|
||||
.It Pa /dev/ppi0
|
||||
default device to be used for communication with the programming
|
||||
Default device to be used for communication with the programming
|
||||
hardware
|
||||
.It Pa avrdude.conf
|
||||
programmer and parts configuration file
|
||||
Programmer and parts configuration file
|
||||
.Pp
|
||||
On Windows systems, this file is looked up in the same directory as the
|
||||
executable file.
|
||||
|
@ -1332,14 +1338,22 @@ On all other systems, the file is first looked up in
|
|||
relative to the path of the executable, then in the same directory as
|
||||
the executable itself, and finally in the system default location
|
||||
.Pa ${PREFIX}/etc/avrdude.conf .
|
||||
.It Pa ${XDG_CONFIG_HOME}/avrdude/avrdude.rc
|
||||
Local programmer and parts configuration file (per-user overrides); it follows the same syntax as
|
||||
.Pa avrdude.conf ;
|
||||
if the
|
||||
.Pa ${XDG_CONFIG_HOME}
|
||||
environment variable is not set or empty, the directory
|
||||
.Pa ${HOME}/.config/
|
||||
is used instead.
|
||||
.It Pa ${HOME}/.avrduderc
|
||||
programmer and parts configuration file (per-user overrides)
|
||||
Alternative location of the per-user configuration file if above file does not exist
|
||||
.It Pa ~/.inputrc
|
||||
Initialization file for the
|
||||
.Xr readline 3
|
||||
library
|
||||
.It Pa ${PREFIX}/share/doc/avrdude/avrdude.pdf
|
||||
Schematic of programming hardware
|
||||
.It Pa <prefix>/doc/avrdude/avrdude.pdf
|
||||
User manual
|
||||
.El
|
||||
.\" .Sh EXAMPLES
|
||||
.Sh DIAGNOSTICS
|
||||
|
|
|
@ -389,7 +389,7 @@
|
|||
# ATmega169 0x78
|
||||
|
||||
#
|
||||
# Overall avrdude defaults; suitable for ~/.avrduderc
|
||||
# Overall avrdude defaults; suitable for ~/.config/avrdude/config
|
||||
#
|
||||
default_parallel = "@DEFAULT_PAR_PORT@";
|
||||
default_serial = "@DEFAULT_SER_PORT@";
|
||||
|
@ -1270,7 +1270,7 @@ programmer
|
|||
id = "stk600";
|
||||
desc = "Atmel STK600";
|
||||
type = "stk600";
|
||||
prog_modes = PM_TPI | PM_ISP;
|
||||
prog_modes = PM_TPI | PM_ISP | PM_PDI;
|
||||
connection_type = usb;
|
||||
;
|
||||
|
||||
|
@ -2294,7 +2294,7 @@ programmer
|
|||
type = "jtagice3_updi";
|
||||
prog_modes = PM_UPDI;
|
||||
connection_type = usb;
|
||||
usbpid = 0x217f, 0x2180, 0x2181;
|
||||
usbpid = 0x2180, 0x217f, 0x2181;
|
||||
hvupdi_support = 1;
|
||||
;
|
||||
|
||||
|
@ -2308,7 +2308,7 @@ programmer
|
|||
type = "jtagice3_pdi";
|
||||
prog_modes = PM_PDI;
|
||||
connection_type = usb;
|
||||
usbpid = 0x217f, 0x2180, 0x2181;
|
||||
usbpid = 0x2180, 0x217f, 0x2181;
|
||||
;
|
||||
|
||||
#------------------------------------------------------------
|
||||
|
@ -2321,7 +2321,7 @@ programmer
|
|||
type = "jtagice3_isp";
|
||||
prog_modes = PM_ISP;
|
||||
connection_type = usb;
|
||||
usbpid = 0x217f, 0x2180, 0x2181;
|
||||
usbpid = 0x2180, 0x217f, 0x2181;
|
||||
;
|
||||
|
||||
#------------------------------------------------------------
|
||||
|
|
|
@ -21,11 +21,14 @@
|
|||
#ifndef avrdude_h
|
||||
#define avrdude_h
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define SYSTEM_CONF_FILE "avrdude.conf"
|
||||
#if defined(WIN32)
|
||||
#define USER_CONF_FILE "avrdude.rc"
|
||||
#else
|
||||
#define USER_CONF_FILE ".avrduderc"
|
||||
#define XDG_USER_CONF_FILE "avrdude/avrdude.rc"
|
||||
#endif
|
||||
|
||||
extern char *progname; // name of program, for messages
|
||||
|
@ -36,7 +39,7 @@ extern int verbose; // verbosity level (-v, -vv, ...)
|
|||
extern int quell_progress; // quell progress report -q, reduce effective verbosity level (-qq, -qqq)
|
||||
|
||||
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_ERROR (-2) // Avrdude error, no -v option, can be suppressed with -qqqq
|
||||
|
@ -49,41 +52,45 @@ int avrdude_message2(const char *fname, int msgmode, int msglvl, const char *for
|
|||
#define MSG_TRACE2 5 // Displayed with -vvvvv
|
||||
|
||||
#define MSG2_PROGNAME 1 // Start by printing progname
|
||||
#define MSG2_FUNCTION 2 // Print calling function (1st arg) after progname
|
||||
#define MSG2_TYPE 4 // Print message type after function or progname
|
||||
#define MSG2_INDENT1 8 // Start by printing indentation of progname+1 blanks
|
||||
#define MSG2_INDENT2 16 // Start by printing indentation of progname+2 blanks
|
||||
#define MSG2_FLUSH 32 // Flush before and after printing
|
||||
#define MSG2_FUNCTION 2 // Print calling function (1st arg) after progname if >= notice
|
||||
#define MSG2_FILELINE 4 // Print source file and line number after function if >= debug
|
||||
#define MSG2_TYPE 8 // Print message type after function or progname
|
||||
#define MSG2_INDENT1 16 // Start by printing indentation of progname+1 blanks
|
||||
#define MSG2_INDENT2 32 // Start by printing indentation of progname+2 blanks
|
||||
#define MSG2_FLUSH 64 // Flush before and after printing
|
||||
|
||||
// Shortcuts
|
||||
#define msg_ext_error(...) avrdude_message2(__func__, 0, MSG_EXT_ERROR, __VA_ARGS__)
|
||||
#define msg_error(...) avrdude_message2(__func__, 0, MSG_ERROR, __VA_ARGS__)
|
||||
#define msg_warning(...) avrdude_message2(__func__, 0, MSG_WARNING, __VA_ARGS__)
|
||||
#define msg_info(...) avrdude_message2(__func__, 0, MSG_INFO, __VA_ARGS__)
|
||||
#define msg_notice(...) avrdude_message2(__func__, 0, MSG_NOTICE, __VA_ARGS__)
|
||||
#define msg_notice2(...) avrdude_message2(__func__, 0, MSG_NOTICE2, __VA_ARGS__)
|
||||
#define msg_debug(...) avrdude_message2(__func__, 0, MSG_DEBUG, __VA_ARGS__)
|
||||
#define msg_trace(...) avrdude_message2(__func__, 0, MSG_TRACE, __VA_ARGS__)
|
||||
#define msg_trace2(...) avrdude_message2(__func__, 0, MSG_TRACE2, __VA_ARGS__)
|
||||
#define msg_ext_error(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, 0, MSG_EXT_ERROR, __VA_ARGS__)
|
||||
#define msg_error(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, 0, MSG_ERROR, __VA_ARGS__)
|
||||
#define msg_warning(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, 0, MSG_WARNING, __VA_ARGS__)
|
||||
#define msg_info(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, 0, MSG_INFO, __VA_ARGS__)
|
||||
#define msg_notice(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, 0, MSG_NOTICE, __VA_ARGS__)
|
||||
#define msg_notice2(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, 0, MSG_NOTICE2, __VA_ARGS__)
|
||||
#define msg_debug(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, 0, MSG_DEBUG, __VA_ARGS__)
|
||||
#define msg_trace(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, 0, MSG_TRACE, __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_error(...) avrdude_message2(__func__, MSG2_PROGNAME|MSG2_FUNCTION|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_info(...) avrdude_message2(__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_notice2(...) avrdude_message2(__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_trace(...) avrdude_message2(__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_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(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FUNCTION|MSG2_FILELINE|MSG2_TYPE|MSG2_FLUSH, MSG_ERROR, __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(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FLUSH, MSG_INFO, __VA_ARGS__)
|
||||
#define pmsg_notice(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FLUSH, MSG_NOTICE, __VA_ARGS__)
|
||||
#define pmsg_notice2(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FLUSH, MSG_NOTICE2, __VA_ARGS__)
|
||||
#define pmsg_debug(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FLUSH, MSG_DEBUG, __VA_ARGS__)
|
||||
#define pmsg_trace(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FLUSH, MSG_TRACE, __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_error(...) avrdude_message2(__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_info(...) avrdude_message2(__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_notice2(...) avrdude_message2(__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_trace(...) avrdude_message2(__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_ext_error(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT1|MSG2_FLUSH, MSG_EXT_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(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT1|MSG2_FLUSH, MSG_WARNING, __VA_ARGS__)
|
||||
#define imsg_info(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT2|MSG2_FLUSH, MSG_INFO, __VA_ARGS__)
|
||||
#define imsg_notice(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT2|MSG2_FLUSH, MSG_NOTICE, __VA_ARGS__)
|
||||
#define imsg_notice2(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT2|MSG2_FLUSH, MSG_NOTICE2, __VA_ARGS__)
|
||||
#define imsg_debug(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT2|MSG2_FLUSH, MSG_DEBUG, __VA_ARGS__)
|
||||
#define imsg_trace(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT2|MSG2_FLUSH, MSG_TRACE, __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
|
||||
|
|
|
@ -498,22 +498,15 @@ void avr_mem_display(const char *prefix, FILE *f, const AVRMEM *m,
|
|||
int i, j;
|
||||
char * optr;
|
||||
|
||||
if (m == NULL) {
|
||||
if (m == NULL || 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);
|
||||
}
|
||||
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
|
||||
if(prev_mem_offset != m->offset || prev_mem_size != m->size || (strcmp(p->family_id, "") == 0)) {
|
||||
prev_mem_offset = m->offset;
|
||||
|
|
|
@ -440,19 +440,21 @@ Override the RS-232 connection baud rate specified in the respective
|
|||
programmer's entry of the configuration file.
|
||||
|
||||
@item -B @var{bitclock}
|
||||
Specify the bit clock period for the JTAG interface or the ISP clock (JTAG ICE only).
|
||||
The value is a floating-point number in microseconds.
|
||||
Alternatively, the value might be suffixed with "Hz", "kHz", or "MHz",
|
||||
in order to specify the bit clock frequency, rather than a period.
|
||||
The default value of the JTAG ICE results in about 1 microsecond bit
|
||||
clock period, suitable for target MCUs running at 4 MHz clock and
|
||||
above.
|
||||
Unlike certain parameters in the STK500, the JTAG ICE resets all its
|
||||
parameters to default values when the programming software signs
|
||||
off from the ICE, so for MCUs running at lower clock speeds, this
|
||||
parameter must be specified on the command-line.
|
||||
It can also be set in the configuration file by using the 'default_bitclock'
|
||||
keyword.
|
||||
Specify the bit clock period for the JTAG, PDI, TPI, UPDI, or ISP
|
||||
interface. The value is a floating-point number in microseconds.
|
||||
Alternatively, the value might be suffixed with "Hz", "kHz" or
|
||||
"MHz" in order to specify the bit clock frequency rather than a
|
||||
period. Some programmers default their bit clock value to a 1
|
||||
microsecond bit clock period, suitable for target MCUs running at 4
|
||||
MHz clock and above. Slower MCUs need a correspondingly higher bit
|
||||
clock period. Some programmers reset their bit clock value to the
|
||||
default value when the programming software signs off, whilst
|
||||
others store the last used bit clock value. It is recommended to
|
||||
always specify the bit clock if read/write speed is important. You
|
||||
can use the 'default_bitclock' keyword in your
|
||||
@code{~/.config/avrdude/avrdude.rc} or @code{~/.avrduderc}
|
||||
configuration file to assign a default value to keep from having to
|
||||
specify this option on every invocation.
|
||||
|
||||
@item -c @var{programmer-id}
|
||||
Specify the programmer to be used. AVRDUDE knows about several common
|
||||
|
@ -598,6 +600,8 @@ Also, for programmers like the Atmel STK500 and STK600 which can
|
|||
adjust parameters local to the programming tool (independent of an
|
||||
actual connection to a target controller), this option can be used
|
||||
together with @option{-t} to continue in terminal mode.
|
||||
Moreover, the option allows to continue despite failed initialization
|
||||
of connection between a programmer and a target.
|
||||
|
||||
@item -i @var{delay}
|
||||
For bitbang-type programmers, delay for approximately
|
||||
|
@ -1714,21 +1718,24 @@ AVRDUDE reads a configuration file upon startup which describes all of
|
|||
the parts and programmers that it knows about. The advantage of this is
|
||||
that if you have a chip that is not currently supported by AVRDUDE, you
|
||||
can add it to the configuration file without waiting for a new release
|
||||
of AVRDUDE. Likewise, if you have a parallel port programmer that is
|
||||
not supported by AVRDUDE, chances are good that you can copy and
|
||||
existing programmer definition, and with only a few changes, make your
|
||||
programmer work with AVRDUDE.
|
||||
of AVRDUDE. Likewise, if you have a parallel port programmer that is
|
||||
not supported, chances are that you can copy an
|
||||
existing programmer definition and, with only a few changes, make your
|
||||
programmer work.
|
||||
|
||||
AVRDUDE first looks for a system wide configuration file in a platform
|
||||
dependent location. On Unix, this is usually
|
||||
@code{/usr/local/etc/avrdude.conf}, while on Windows it is usually in the
|
||||
same location as the executable file. The name of this file can be
|
||||
changed using the @option{-C} command line option. After the system wide
|
||||
configuration file is parsed, AVRDUDE looks for a per-user configuration
|
||||
@code{/usr/local/etc/avrdude.conf}, whilst on Windows it is usually in the
|
||||
same location as the executable file. The full name of this file can be
|
||||
specified using the @option{-C} command line option. After parsing the system wide
|
||||
configuration file, AVRDUDE looks for a per-user configuration
|
||||
file to augment or override the system wide defaults. On Unix, the
|
||||
per-user file is @code{.avrduderc} within the user's home directory. On
|
||||
Windows, this file is the @code{avrdude.rc} file located in the same
|
||||
directory as the executable.
|
||||
per-user file is @code{$@{XDG_CONFIG_HOME@}/avrdude/avrdude.rc}, whereas
|
||||
if @code{$@{XDG_CONFIG_HOME@}} is either not set or empty,
|
||||
@code{$@{HOME@}/.config/} is used instead. If that does not exists
|
||||
@code{.avrduderc} within the user's home directory is used. On Windows,
|
||||
this file is the @code{avrdude.rc} file located in the same directory as
|
||||
the executable.
|
||||
|
||||
@menu
|
||||
* AVRDUDE Defaults::
|
||||
|
@ -3044,14 +3051,15 @@ See also: @url{http://www.libusb.org/ticket/6}
|
|||
@item
|
||||
Problem: after flashing a firmware that reduces the target's clock
|
||||
speed (e.g. through the @code{CLKPR} register), further ISP connection
|
||||
attempts fail.
|
||||
attempts fail. Or a programmer cannot initialize communication with
|
||||
a brand new chip.
|
||||
|
||||
Solution: Even though ISP starts with pulling @var{/RESET} low, the
|
||||
target continues to run at the internal clock speed as defined by the
|
||||
firmware running before. Therefore, the ISP clock speed must be
|
||||
reduced appropriately (to less than 1/4 of the internal clock speed)
|
||||
using the -B option before the ISP initialization sequence will
|
||||
succeed.
|
||||
target continues to run at the internal clock speed either as defined by
|
||||
the firmware running before or as set by the factory. Therefore, the
|
||||
ISP clock speed must be reduced appropriately (to less than 1/4 of the
|
||||
internal clock speed) using the -B option before the ISP initialization
|
||||
sequence will succeed.
|
||||
|
||||
As that slows down the entire subsequent ISP session, it might make
|
||||
sense to just issue a @emph{chip erase} using the slow ISP clock
|
||||
|
|
|
@ -121,6 +121,8 @@ enum flip2_mem_unit {
|
|||
FLIP2_MEM_UNIT_EXT_MEM_DF = 0x10
|
||||
};
|
||||
|
||||
#ifdef HAVE_LIBUSB
|
||||
|
||||
/* EXPORTED PROGRAMMER FUNCTION PROTOTYPES */
|
||||
|
||||
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);
|
||||
|
||||
/* 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);
|
||||
|
||||
|
|
56
src/jtag3.c
56
src/jtag3.c
|
@ -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,
|
||||
unsigned long addr, unsigned char data);
|
||||
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,
|
||||
unsigned int page_size,
|
||||
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)
|
||||
return -1;
|
||||
}
|
||||
jtag3_print_parms1(pgm, progbuf);
|
||||
jtag3_print_parms1(pgm, progbuf, stderr);
|
||||
if (conn == PARM3_CONN_JTAG)
|
||||
{
|
||||
pmsg_notice2("jtag3_initialize(): "
|
||||
|
@ -1504,6 +1504,30 @@ int jtag3_open_common(PROGRAMMER *pgm, const char *port) {
|
|||
}
|
||||
#endif
|
||||
if (rv < 0) {
|
||||
// Check if SNAP or PICkit4 is in PIC mode
|
||||
for(LNODEID ln=lfirst(pgm->id); ln; ln=lnext(ln)) {
|
||||
if (matches(ldata(ln), "snap")) {
|
||||
pinfo.usbinfo.vid = USB_VENDOR_MICROCHIP;
|
||||
pinfo.usbinfo.pid = USB_DEVICE_SNAP_PIC_MODE;
|
||||
int pic_mode = serial_open(port, pinfo, &pgm->fd);
|
||||
if(pic_mode >= 0) {
|
||||
msg_error("\n");
|
||||
pmsg_error("MPLAB SNAP in PIC mode detected!\n");
|
||||
imsg_error("Use MPLAB X or Microchip Studio to switch to AVR mode\n\n");
|
||||
return -1;
|
||||
}
|
||||
} else if(matches(ldata(ln), "pickit4")) {
|
||||
pinfo.usbinfo.vid = USB_VENDOR_MICROCHIP;
|
||||
pinfo.usbinfo.pid = USB_DEVICE_PICKIT4_PIC_MODE;
|
||||
int pic_mode = serial_open(port, pinfo, &pgm->fd);
|
||||
if(pic_mode >= 0) {
|
||||
msg_error("\n");
|
||||
pmsg_error("PICkit4 in PIC mode detected!\n");
|
||||
imsg_error("Use MPLAB X or Microchip Studio to switch to AVR mode\n\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
pmsg_error("did not find any device matching VID 0x%04x and PID list: ",
|
||||
(unsigned) pinfo.usbinfo.vid);
|
||||
int notfirst = 0;
|
||||
|
@ -2333,12 +2357,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];
|
||||
|
||||
if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_VTARGET, buf, 2) < 0)
|
||||
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);
|
||||
|
||||
// Print features unique to the Power Debugger
|
||||
|
@ -2350,7 +2374,7 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p) {
|
|||
if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_VADJUST, buf, 2) < 0)
|
||||
return;
|
||||
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);
|
||||
|
||||
// Read measured generator voltage value (VOUT)
|
||||
|
@ -2362,7 +2386,7 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p) {
|
|||
else {
|
||||
if (analog_raw_data & 0x0800)
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -2375,7 +2399,7 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p) {
|
|||
else {
|
||||
if (analog_raw_data & 0x0800)
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -2386,7 +2410,7 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p) {
|
|||
if (buf[0] != 0x90)
|
||||
pmsg_error("invalid PARM3_ANALOG_A_CURRENT data packet format\n");
|
||||
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);
|
||||
|
||||
// Read channel B voltage
|
||||
|
@ -2398,7 +2422,7 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p) {
|
|||
else {
|
||||
if (analog_raw_data & 0x0800)
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -2411,7 +2435,7 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p) {
|
|||
else {
|
||||
if (analog_raw_data & 0x0800)
|
||||
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);
|
||||
}
|
||||
break;
|
||||
|
@ -2422,33 +2446,33 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p) {
|
|||
return;
|
||||
|
||||
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)
|
||||
return;
|
||||
|
||||
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)
|
||||
return;
|
||||
|
||||
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)
|
||||
return;
|
||||
|
||||
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) {
|
||||
jtag3_print_parms1(pgm, "");
|
||||
static void jtag3_print_parms(const PROGRAMMER *pgm, FILE *fp) {
|
||||
jtag3_print_parms1(pgm, "", fp);
|
||||
}
|
||||
|
||||
static unsigned char jtag3_memtype(const PROGRAMMER *pgm, const AVRPART *p, unsigned long addr) {
|
||||
|
|
|
@ -38,7 +38,7 @@ int jtag3_setparm(const PROGRAMMER *pgm, unsigned char scope,
|
|||
unsigned char *value, unsigned char length);
|
||||
int jtag3_command(const PROGRAMMER *pgm, unsigned char *cmd, unsigned int cmdlen,
|
||||
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);
|
||||
extern const char jtag3_desc[];
|
||||
extern const char jtag3_dw_desc[];
|
||||
|
|
|
@ -104,7 +104,7 @@ static int jtagmkI_getparm(const PROGRAMMER *pgm, unsigned char parm,
|
|||
unsigned char * value);
|
||||
static int jtagmkI_setparm(const PROGRAMMER *pgm, unsigned char parm,
|
||||
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);
|
||||
|
||||
|
@ -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 FW version: 0x%02x\n", p, fw);
|
||||
|
||||
jtagmkI_print_parms1(pgm, p);
|
||||
jtagmkI_print_parms1(pgm, p, stderr);
|
||||
|
||||
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;
|
||||
const char *clkstr;
|
||||
double clk;
|
||||
|
@ -1211,15 +1211,15 @@ static void jtagmkI_print_parms1(const PROGRAMMER *pgm, const char *p) {
|
|||
clk = 1e6;
|
||||
}
|
||||
|
||||
msg_info("%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, "%sVtarget : %.1f V\n", p, 6.25 * (unsigned)vtarget / 255.0);
|
||||
fmsg_out(fp, "%sJTAG clock : %s (%.1f us)\n", p, clkstr, 1.0e6 / clk);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static void jtagmkI_print_parms(const PROGRAMMER *pgm) {
|
||||
jtagmkI_print_parms1(pgm, "");
|
||||
static void jtagmkI_print_parms(const PROGRAMMER *pgm, FILE *fp) {
|
||||
jtagmkI_print_parms1(pgm, "", fp);
|
||||
}
|
||||
|
||||
const char jtagmkI_desc[] = "Atmel JTAG ICE mkI";
|
||||
|
|
|
@ -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_setparm(const PROGRAMMER *pgm, unsigned char parm,
|
||||
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,
|
||||
unsigned int page_size,
|
||||
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[3], PDATA(pgm)->serno[4], PDATA(pgm)->serno[5]);
|
||||
|
||||
jtagmkII_print_parms1(pgm, p);
|
||||
jtagmkII_print_parms1(pgm, p, stderr);
|
||||
|
||||
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];
|
||||
char clkbuf[20];
|
||||
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)
|
||||
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 (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]);
|
||||
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;
|
||||
}
|
||||
|
||||
static void jtagmkII_print_parms(const PROGRAMMER *pgm) {
|
||||
jtagmkII_print_parms1(pgm, "");
|
||||
static void jtagmkII_print_parms(const PROGRAMMER *pgm, FILE *fp) {
|
||||
jtagmkII_print_parms1(pgm, "", fp);
|
||||
}
|
||||
|
||||
static unsigned char jtagmkII_memtype(const PROGRAMMER *pgm, const AVRPART *p, unsigned long addr) {
|
||||
|
|
|
@ -783,7 +783,8 @@ typedef struct programmer_t {
|
|||
unsigned long addr, unsigned char *value);
|
||||
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);
|
||||
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_varef) (const struct programmer_t *pgm, unsigned int chan, double v);
|
||||
int (*set_fosc) (const struct programmer_t *pgm, double v);
|
||||
|
|
85
src/main.c
85
src/main.c
|
@ -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;
|
||||
va_list ap;
|
||||
|
||||
if(msglvl <= MSG_ERROR) // Serious error? Freee progress bars (if any)
|
||||
report_progress(1, -1, NULL);
|
||||
|
||||
if(msgmode & MSG2_FLUSH) {
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
// Reduce effective verbosity level by number of -q above one
|
||||
if ((quell_progress < 2? verbose: verbose+1-quell_progress) >= msglvl) {
|
||||
// Reduce effective verbosity level by number of -q above one when printing to stderr
|
||||
if ((quell_progress < 2 || fp != stderr? verbose: verbose+1-quell_progress) >= msglvl) {
|
||||
if(msgmode & MSG2_PROGNAME) {
|
||||
fprintf(stderr, "%s", progname);
|
||||
fprintf(fp, "%s", progname);
|
||||
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)
|
||||
fprintf(stderr, " %s", avrdude_message_type(msglvl));
|
||||
fprintf(stderr, ": ");
|
||||
fprintf(fp, " %s", avrdude_message_type(msglvl));
|
||||
fprintf(fp, ": ");
|
||||
} else if(msgmode & MSG2_INDENT1) {
|
||||
fprintf(stderr, "%*s", (int) strlen(progname)+1, "");
|
||||
fprintf(fp, "%*s", (int) strlen(progname)+1, "");
|
||||
} else if(msgmode & MSG2_INDENT2) {
|
||||
fprintf(stderr, "%*s", (int) strlen(progname)+2, "");
|
||||
fprintf(fp, "%*s", (int) strlen(progname)+2, "");
|
||||
}
|
||||
va_start(ap, format);
|
||||
rc = vfprintf(stderr, format, ap);
|
||||
rc = vfprintf(fp, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
if(msgmode & MSG2_FLUSH)
|
||||
fflush(stderr);
|
||||
fflush(fp);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -155,14 +167,14 @@ static void usage(void)
|
|||
"Options:\n"
|
||||
" -p <partno> Specify AVR device\n"
|
||||
" -b <baudrate> Override RS-232 baud rate\n"
|
||||
" -B <bitclock> Specify JTAG/STK500v2 bit clock period (us)\n"
|
||||
" -B <bitclock> Specify bit clock period (us)\n"
|
||||
" -C <config-file> Specify location of configuration file\n"
|
||||
" -c <programmer> Specify programmer type\n"
|
||||
" -A Disable trailing-0xff removal from file and AVR read\n"
|
||||
" -D Disable auto erase for flash memory; implies -A\n"
|
||||
" -i <delay> ISP Clock Delay [in microseconds]\n"
|
||||
" -P <port> Specify connection port\n"
|
||||
" -F Override invalid signature check\n"
|
||||
" -F Override invalid signature or initialisation check\n"
|
||||
" -e Perform a chip erase\n"
|
||||
" -O Perform RC oscillator calibration (see AVR053)\n"
|
||||
" -U <memtype>:r|w|v:<filename>[:format]\n"
|
||||
|
@ -425,6 +437,32 @@ static void exit_part_not_found(const char *partdesc) {
|
|||
}
|
||||
|
||||
|
||||
#if !defined(WIN32)
|
||||
// Safely concatenate dir/file into dst that has size n
|
||||
static char *concatpath(char *dst, char *dir, char *file, size_t n) {
|
||||
// Dir or file empty?
|
||||
if(!dir || !*dir || !file || !*file)
|
||||
return NULL;
|
||||
|
||||
size_t len = strlen(dir);
|
||||
|
||||
// Insufficient space?
|
||||
if(len + (dir[len-1] != '/') + strlen(file) > n-1)
|
||||
return NULL;
|
||||
|
||||
if(dst != dir)
|
||||
strcpy(dst, dir);
|
||||
|
||||
if(dst[len-1] != '/')
|
||||
strcat(dst, "/");
|
||||
|
||||
strcat(dst, file);
|
||||
|
||||
return dst;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* main routine
|
||||
*/
|
||||
|
@ -465,10 +503,6 @@ int main(int argc, char * argv [])
|
|||
char * logfile; /* Use logfile rather than stderr for diagnostics */
|
||||
enum updateflags uflags = UF_AUTO_ERASE | UF_VERIFY; /* Flags for do_op() */
|
||||
|
||||
#if !defined(WIN32)
|
||||
char * homedir;
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
_set_printf_count_output(1);
|
||||
#endif
|
||||
|
@ -856,14 +890,10 @@ int main(int argc, char * argv [])
|
|||
win_usr_config_set(usr_config);
|
||||
#else
|
||||
usr_config[0] = 0;
|
||||
homedir = getenv("HOME");
|
||||
if (homedir != NULL) {
|
||||
strcpy(usr_config, homedir);
|
||||
i = strlen(usr_config);
|
||||
if (i && (usr_config[i - 1] != '/'))
|
||||
strcat(usr_config, "/");
|
||||
strcat(usr_config, USER_CONF_FILE);
|
||||
}
|
||||
if(!concatpath(usr_config, getenv("XDG_CONFIG_HOME"), XDG_USER_CONF_FILE, sizeof usr_config))
|
||||
concatpath(usr_config, getenv("HOME"), ".config/" XDG_USER_CONF_FILE, sizeof usr_config);
|
||||
if(stat(usr_config, &sb) < 0 || (sb.st_mode & S_IFREG) == 0)
|
||||
concatpath(usr_config, getenv("HOME"), USER_CONF_FILE, sizeof usr_config);
|
||||
#endif
|
||||
|
||||
if (quell_progress == 0)
|
||||
|
@ -1190,9 +1220,10 @@ int main(int argc, char * argv [])
|
|||
init_ok = (rc = pgm->initialize(pgm, p)) >= 0;
|
||||
if (!init_ok) {
|
||||
pmsg_error("initialization failed, rc=%d\n", rc);
|
||||
imsg_error("- double check the connections and try again\n");
|
||||
imsg_error("- use -B to set lower ISP clock frequency, e.g. -B 200kHz\n");
|
||||
if (!ovsigck) {
|
||||
imsg_error("double check connections and try again or use -F to override\n");
|
||||
imsg_error("this check\n\n");
|
||||
imsg_error("- use -F to override this check\n\n");
|
||||
exitrc = 1;
|
||||
goto main_exit;
|
||||
}
|
||||
|
|
|
@ -140,6 +140,7 @@ PROGRAMMER *pgm_new(void) {
|
|||
pgm->write_setup = NULL;
|
||||
pgm->read_sig_bytes = NULL;
|
||||
pgm->read_sib = NULL;
|
||||
pgm->term_keep_alive= NULL;
|
||||
pgm->print_parms = NULL;
|
||||
pgm->set_vtarget = NULL;
|
||||
pgm->set_varef = NULL;
|
||||
|
|
142
src/stk500.c
142
src/stk500.c
|
@ -47,7 +47,7 @@
|
|||
|
||||
static int stk500_getparm(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) {
|
||||
|
@ -625,6 +625,12 @@ static void stk500_disable(const PROGRAMMER *pgm) {
|
|||
}
|
||||
|
||||
static void stk500_enable(PROGRAMMER *pgm, const AVRPART *p) {
|
||||
AVRMEM *mem;
|
||||
if(pgm->prog_modes & PM_SPM) // For bootloaders (eg, arduino)
|
||||
if(!(p->prog_modes & (PM_UPDI | PM_PDI | PM_aWire))) // Classic parts, eg, optiboot with word addresses
|
||||
if((mem = avr_locate_mem(p, "eeprom")))
|
||||
if(mem->page_size == 1) // Increase pagesize if it is 1
|
||||
mem->page_size = 16;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -666,27 +672,56 @@ static void stk500_close(PROGRAMMER * pgm)
|
|||
}
|
||||
|
||||
|
||||
static int stk500_loadaddr(const PROGRAMMER *pgm, const AVRMEM *mem, const unsigned int addr) {
|
||||
// Address is byte address; a_div == 2: send word address; a_div == 1: send byte address
|
||||
static int stk500_loadaddr(const PROGRAMMER *pgm, const AVRMEM *mem, unsigned int addr, int a_div) {
|
||||
unsigned char buf[16];
|
||||
int tries;
|
||||
unsigned char ext_byte;
|
||||
OPCODE * lext;
|
||||
|
||||
addr /= a_div;
|
||||
|
||||
tries = 0;
|
||||
retry:
|
||||
tries++;
|
||||
|
||||
/* To support flash > 64K words the correct Extended Address Byte is needed */
|
||||
lext = mem->op[AVR_OP_LOAD_EXT_ADDR];
|
||||
if (lext != NULL) {
|
||||
ext_byte = (addr >> 16) & 0xff;
|
||||
if (ext_byte != PDATA(pgm)->ext_addr_byte) {
|
||||
/* Either this is the first addr load, or a different 64K word section */
|
||||
memset(buf, 0, 4);
|
||||
avr_set_bits(lext, buf);
|
||||
avr_set_addr(lext, buf, addr);
|
||||
stk500_cmd(pgm, buf, buf);
|
||||
PDATA(pgm)->ext_addr_byte = ext_byte;
|
||||
// Support large flash by sending the correct extended address byte when needed
|
||||
|
||||
if(pgm->prog_modes & PM_SPM) { // Bootloaders, eg, optiboot, optiboot_dx, optiboot_x
|
||||
if(mem->size/a_div > 64*1024) { // Extended addressing needed
|
||||
ext_byte = (addr >> 16) & 0xff;
|
||||
if(ext_byte != PDATA(pgm)->ext_addr_byte) { // First addr load or a different 64k section
|
||||
buf[0] = 0x4d; // Protocol bytes that bootloaders expect
|
||||
buf[1] = 0x00;
|
||||
buf[2] = ext_byte;
|
||||
buf[3] = 0x00;
|
||||
if(stk500_cmd(pgm, buf, buf) == 0)
|
||||
PDATA(pgm)->ext_addr_byte = ext_byte;
|
||||
}
|
||||
/*
|
||||
* Ensure next paged r/w will load ext addr again if page sits just below a 64k boundary
|
||||
*
|
||||
* Some bootloaders increment their copy of ext_addr_byte in that situation, eg, when they
|
||||
* use elpm rx,Z+ to read a byte from flash or spm Z+ to write to flash whilst they keep
|
||||
* ext_addr_byte in RAMPZ, which in turn gets incremented by Z+ at 64k page boundaries. So,
|
||||
* if an upload with automated verify finishes just below 64k, AVRDUDE still holds
|
||||
* ext_addr_byte at the current 64k segment whilst its copy in the bootloader has been
|
||||
* auto-incremented. Verifying the code from start exposes the discrepancy.
|
||||
*/
|
||||
if((addr & 0xffff0000) != ((addr+mem->page_size/a_div) & 0xffff0000))
|
||||
PDATA(pgm)->ext_addr_byte = 0xff;
|
||||
}
|
||||
} else { // Programmer *not* for bootloaders? Original stk500v1 protocol!
|
||||
OPCODE *lext = mem->op[AVR_OP_LOAD_EXT_ADDR];
|
||||
|
||||
if(lext) {
|
||||
ext_byte = (addr >> 16) & 0xff;
|
||||
if(ext_byte != PDATA(pgm)->ext_addr_byte) { // First addr load or a different 64k section
|
||||
memset(buf, 0, 4); // Part's load_ext_addr command is typically 4d 00 ext_addr 00
|
||||
avr_set_bits(lext, buf);
|
||||
avr_set_addr(lext, buf, addr);
|
||||
if(stk500_cmd(pgm, buf, buf) == 0)
|
||||
PDATA(pgm)->ext_addr_byte = ext_byte;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -724,6 +759,29 @@ static int stk500_loadaddr(const PROGRAMMER *pgm, const AVRMEM *mem, const unsig
|
|||
}
|
||||
|
||||
|
||||
static int set_memtype_a_div(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m, int *memtypep, int *a_divp) {
|
||||
if(avr_mem_is_flash_type(m)) {
|
||||
*memtypep = 'F';
|
||||
if(!(pgm->prog_modes & PM_SPM)) // Programmer *not* for bootloaders: original stk500v1 protocol
|
||||
*a_divp = m->op[AVR_OP_LOADPAGE_LO] || m->op[AVR_OP_READ_LO]? 2: 1;
|
||||
else if(!(p->prog_modes & (PM_UPDI | PM_PDI | PM_aWire)))
|
||||
*a_divp = 2; // Bootloader where part is a "classic" part (eg, optiboot)
|
||||
else
|
||||
*a_divp = 1; // Bootloader where part is Xmega or "new" families (optiboot_x, optiboot_dx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(avr_mem_is_eeprom_type(m)) {
|
||||
*memtypep = 'E';
|
||||
// Word addr for bootloaders where part is a "classic" part (eg, optiboot, arduinoisp, ...), byte addr otherwise
|
||||
*a_divp = (pgm->prog_modes & PM_SPM) && !(p->prog_modes & (PM_UPDI | PM_PDI))? 2: 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static int stk500_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
|
||||
unsigned int page_size,
|
||||
unsigned int addr, unsigned int n_bytes)
|
||||
|
@ -736,25 +794,12 @@ static int stk500_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVR
|
|||
unsigned int n;
|
||||
unsigned int i;
|
||||
|
||||
if (strcmp(m->desc, "flash") == 0) {
|
||||
memtype = 'F';
|
||||
a_div = 2;
|
||||
} else if (strcmp(m->desc, "eeprom") == 0) {
|
||||
memtype = 'E';
|
||||
/*
|
||||
* The STK original 500 v1 protocol actually expects a_div = 1, but the
|
||||
* v1.x FW of the STK500 kit has been superseded by v2 FW in the mid
|
||||
* 2000s. Since optiboot, arduino as ISP and others assume a_div = 2,
|
||||
* better use that. See https://github.com/avrdudes/avrdude/issues/967
|
||||
*/
|
||||
a_div = 2;
|
||||
} else {
|
||||
if(set_memtype_a_div(pgm, p, m, &memtype, &a_div) < 0)
|
||||
return -2;
|
||||
}
|
||||
|
||||
n = addr + n_bytes;
|
||||
#if 0
|
||||
msg_info(
|
||||
msg_debug(
|
||||
"n_bytes = %d\n"
|
||||
"n = %u\n"
|
||||
"a_div = %d\n"
|
||||
|
@ -775,7 +820,7 @@ static int stk500_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVR
|
|||
tries = 0;
|
||||
retry:
|
||||
tries++;
|
||||
stk500_loadaddr(pgm, m, addr/a_div);
|
||||
stk500_loadaddr(pgm, m, addr, a_div);
|
||||
|
||||
/* build command block and avoid multiple send commands as it leads to a crash
|
||||
of the silabs usb serial driver on mac os x */
|
||||
|
@ -830,21 +875,8 @@ static int stk500_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AVRM
|
|||
unsigned int n;
|
||||
int block_size;
|
||||
|
||||
if (strcmp(m->desc, "flash") == 0) {
|
||||
memtype = 'F';
|
||||
a_div = 2;
|
||||
} else if (strcmp(m->desc, "eeprom") == 0) {
|
||||
memtype = 'E';
|
||||
/*
|
||||
* The STK original 500 v1 protocol actually expects a_div = 1, but the
|
||||
* v1.x FW of the STK500 kit has been superseded by v2 FW in the mid
|
||||
* 2000s. Since optiboot, arduino as ISP and others assume a_div = 2,
|
||||
* better use that. See https://github.com/avrdudes/avrdude/issues/967
|
||||
*/
|
||||
a_div = 2;
|
||||
} else {
|
||||
if(set_memtype_a_div(pgm, p, m, &memtype, &a_div) < 0)
|
||||
return -2;
|
||||
}
|
||||
|
||||
n = addr + n_bytes;
|
||||
for (; addr < n; addr += block_size) {
|
||||
|
@ -861,7 +893,7 @@ static int stk500_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AVRM
|
|||
tries = 0;
|
||||
retry:
|
||||
tries++;
|
||||
stk500_loadaddr(pgm, m, addr/a_div);
|
||||
stk500_loadaddr(pgm, m, addr, a_div);
|
||||
buf[0] = Cmnd_STK_READ_PAGE;
|
||||
buf[1] = (block_size >> 8) & 0xff;
|
||||
buf[2] = block_size & 0xff;
|
||||
|
@ -1160,13 +1192,13 @@ static void stk500_display(const PROGRAMMER *pgm, const char *p) {
|
|||
msg_info("%sTopcard : %s\n", p, n);
|
||||
}
|
||||
if(strcmp(pgm->type, "Arduino") != 0)
|
||||
stk500_print_parms1(pgm, p);
|
||||
stk500_print_parms1(pgm, p, stderr);
|
||||
|
||||
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;
|
||||
|
||||
stk500_getparm(pgm, Parm_STK_VTARGET, &vtarget);
|
||||
|
@ -1175,11 +1207,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_SCK_DURATION, &sck_duration);
|
||||
|
||||
msg_info("%sVtarget : %.1f V\n", p, vtarget / 10.0);
|
||||
msg_info("%sVaref : %.1f V\n", p, vadjust / 10.0);
|
||||
msg_info("%sOscillator : ", p);
|
||||
fmsg_out(fp, "%sVtarget : %.1f V\n", p, vtarget / 10.0);
|
||||
fmsg_out(fp, "%sVaref : %.1f V\n", p, vadjust / 10.0);
|
||||
fmsg_out(fp, "%sOscillator : ", p);
|
||||
if (osc_pscale == 0)
|
||||
msg_info("Off\n");
|
||||
fmsg_out(fp, "Off\n");
|
||||
else {
|
||||
int prescale = 1;
|
||||
double f = STK500_XTAL / 2;
|
||||
|
@ -1203,16 +1235,16 @@ static void stk500_print_parms1(const PROGRAMMER *pgm, const char *p) {
|
|||
unit = "kHz";
|
||||
} else
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
static void stk500_print_parms(const PROGRAMMER *pgm) {
|
||||
stk500_print_parms1(pgm, "");
|
||||
static void stk500_print_parms(const PROGRAMMER *pgm, FILE *fp) {
|
||||
stk500_print_parms1(pgm, "", fp);
|
||||
}
|
||||
|
||||
static void stk500_setup(PROGRAMMER * pgm)
|
||||
|
|
|
@ -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_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 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,
|
||||
unsigned int page_size,
|
||||
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);
|
||||
msg_info("%sEC_ID table rev : %d\n", p, rev);
|
||||
}
|
||||
stk500v2_print_parms1(pgm, p);
|
||||
stk500v2_print_parms1(pgm, p, stderr);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -3095,7 +3095,7 @@ f_to_kHz_MHz(double f, const char **unit)
|
|||
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 int sck_stk600, clock_conf, dac, oct, varef;
|
||||
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;
|
||||
jtagmkII_getparm(pgmcp, PAR_OCD_VTARGET, vtarget_jtag);
|
||||
pgm_free(pgmcp);
|
||||
msg_info("%sVtarget : %.1f V\n", p,
|
||||
b2_to_u16(vtarget_jtag) / 1000.0);
|
||||
fmsg_out(fp, "%sVtarget : %.1f V\n", p, b2_to_u16(vtarget_jtag) / 1000.0);
|
||||
} else if (PDATA(pgm)->pgmtype == PGMTYPE_JTAGICE3) {
|
||||
PROGRAMMER *pgmcp = pgm_dup(pgm);
|
||||
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
|
||||
for(LNODEID ln=lfirst(pgm->id); ln; ln=lnext(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);
|
||||
} else {
|
||||
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) {
|
||||
|
@ -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_OSC_PSCALE, &osc_pscale);
|
||||
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));
|
||||
msg_info("%sVaref : %.1f V\n", p, vadjust / 10.0);
|
||||
msg_info("%sOscillator : ", p);
|
||||
fmsg_out(fp, "%sVaref : %.1f V\n", p, vadjust / 10.0);
|
||||
fmsg_out(fp, "%sOscillator : ", p);
|
||||
if (osc_pscale == 0)
|
||||
msg_info("Off\n");
|
||||
fmsg_out(fp, "Off\n");
|
||||
else {
|
||||
prescale = 1;
|
||||
f = STK500V2_XTAL / 2;
|
||||
|
@ -3153,14 +3152,14 @@ static void stk500v2_print_parms1(const PROGRAMMER *pgm, const char *p) {
|
|||
f /= prescale;
|
||||
f /= (osc_cmatch + 1);
|
||||
f = f_to_kHz_MHz(f, &unit);
|
||||
msg_info("%.3f %s\n", f, unit);
|
||||
fmsg_out(fp, "%.3f %s\n", f, unit);
|
||||
}
|
||||
break;
|
||||
|
||||
case PGMTYPE_AVRISP_MKII:
|
||||
case PGMTYPE_JTAGICE_MKII:
|
||||
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]);
|
||||
break;
|
||||
|
||||
|
@ -3172,7 +3171,7 @@ static void stk500v2_print_parms1(const PROGRAMMER *pgm, const char *p) {
|
|||
if (stk500v2_jtag3_send(pgm, cmd, 1) >= 0 &&
|
||||
stk500v2_jtag3_recv(pgm, cmd, 4) >= 2) {
|
||||
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)));
|
||||
}
|
||||
}
|
||||
|
@ -3180,23 +3179,23 @@ static void stk500v2_print_parms1(const PROGRAMMER *pgm, const char *p) {
|
|||
|
||||
case PGMTYPE_STK600:
|
||||
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);
|
||||
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);
|
||||
msg_info("%sSCK period : %.2f us\n", p,
|
||||
fmsg_out(fp, "%sSCK period : %.2f us\n", p,
|
||||
(float) (sck_stk600 + 1) / 8.0);
|
||||
stk500v2_getparm2(pgm, PARAM2_CLOCK_CONF, &clock_conf);
|
||||
oct = (clock_conf & 0xf000) >> 12u;
|
||||
dac = (clock_conf & 0x0ffc) >> 2u;
|
||||
f = pow(2, (double)oct) * 2078.0 / (2 - (double)dac / 1024.0);
|
||||
f = f_to_kHz_MHz(f, &unit);
|
||||
msg_info("%sOscillator : %.3f %s\n",
|
||||
fmsg_out(fp, "%sOscillator : %.3f %s\n",
|
||||
p, f, unit);
|
||||
break;
|
||||
|
||||
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);
|
||||
break;
|
||||
}
|
||||
|
@ -3205,8 +3204,8 @@ static void stk500v2_print_parms1(const PROGRAMMER *pgm, const char *p) {
|
|||
}
|
||||
|
||||
|
||||
static void stk500v2_print_parms(const PROGRAMMER *pgm) {
|
||||
stk500v2_print_parms1(pgm, "");
|
||||
static void stk500v2_print_parms(const PROGRAMMER *pgm, FILE *fp) {
|
||||
stk500v2_print_parms1(pgm, "", fp);
|
||||
}
|
||||
|
||||
static int stk500v2_perform_osccal(const PROGRAMMER *pgm) {
|
||||
|
|
455
src/term.c
455
src/term.c
|
@ -33,10 +33,21 @@
|
|||
#include <errno.h>
|
||||
|
||||
#if defined(HAVE_LIBREADLINE)
|
||||
# include <readline/readline.h>
|
||||
# include <readline/history.h>
|
||||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include "msvc/unistd.h"
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#include "avrdude.h"
|
||||
#include "term.h"
|
||||
|
||||
|
@ -114,7 +125,7 @@ static int nexttok(char *buf, char **tok, char **next) {
|
|||
n = q;
|
||||
uint8_t quotes = 0;
|
||||
while (*n && (!isspace(*n) || quotes)) {
|
||||
// poor man's quote and escape processing
|
||||
// Poor man's quote and escape processing
|
||||
if (*n == '"' || *n == '\'')
|
||||
quotes++;
|
||||
else if(*n == '\\' && n[1])
|
||||
|
@ -173,7 +184,7 @@ static int chardump_line(char *buffer, unsigned char *p, int n, int pad) {
|
|||
int i;
|
||||
unsigned char b[128];
|
||||
|
||||
// sanity check
|
||||
// Sanity check
|
||||
n = n < 1? 1: n > sizeof b? sizeof b: n;
|
||||
|
||||
memcpy(b, p, n);
|
||||
|
@ -202,7 +213,7 @@ static int hexdump_buf(FILE *f, int startaddr, unsigned char *buf, int len) {
|
|||
n = len;
|
||||
hexdump_line(dst1, p, n, 48);
|
||||
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;
|
||||
addr += 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[]) {
|
||||
if (argc < 2 || argc > 4) {
|
||||
terminal_message(MSG_INFO,
|
||||
msg_error(
|
||||
"Usage: %s <memory> <addr> <len>\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];
|
||||
AVRMEM *mem = avr_locate_mem(p, memtype);
|
||||
if (mem == NULL) {
|
||||
terminal_message(MSG_INFO, "%s (dump): %s memory type not defined for part %s\n",
|
||||
progname, memtype, p->desc);
|
||||
pmsg_error("(dump) %s memory type not defined for part %s\n", memtype, p->desc);
|
||||
return -1;
|
||||
}
|
||||
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) {
|
||||
addr = strtoul(argv[2], &end_ptr, 0);
|
||||
if (*end_ptr || (end_ptr == argv[2])) {
|
||||
terminal_message(MSG_INFO, "%s (dump): can't parse address %s\n",
|
||||
progname, argv[2]);
|
||||
pmsg_error("(dump) cannot parse address %s\n", argv[2]);
|
||||
return -1;
|
||||
} 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);
|
||||
pmsg_error("(dump) %s address 0x%05x is out of range [0, 0x%05x]\n", mem->desc, addr, maxsize-1);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -263,8 +271,7 @@ static int cmd_dump(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
|||
} else if (argc == 4) {
|
||||
len = strtol(argv[3], &end_ptr, 0);
|
||||
if (*end_ptr || (end_ptr == argv[3])) {
|
||||
terminal_message(MSG_INFO, "%s (dump): can't parse length %s\n",
|
||||
progname, argv[3]);
|
||||
pmsg_error("(dump) cannot parse length %s\n", argv[3]);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
|
@ -288,7 +295,7 @@ static int cmd_dump(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
|||
|
||||
uint8_t *buf = malloc(len);
|
||||
if (buf == NULL) {
|
||||
terminal_message(MSG_INFO, "%s (dump): out of memory\n", progname);
|
||||
pmsg_error("(dump) out of memory\n");
|
||||
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]);
|
||||
if (rc != 0) {
|
||||
report_progress(1, -1, NULL);
|
||||
terminal_message(MSG_INFO, "%s (dump): error reading %s address 0x%05lx of part %s\n",
|
||||
progname, mem->desc, (long) addr + i, p->desc);
|
||||
pmsg_error("(dump) error reading %s address 0x%05lx of part %s\n", mem->desc, (long) addr + i, p->desc);
|
||||
if (rc == -1)
|
||||
terminal_message(MSG_INFO, "%*sread operation not supported on memory type %s\n",
|
||||
(int) strlen(progname)+9, "", mem->desc);
|
||||
imsg_error("%*sread operation not supported on memory type %s\n", 7, "", mem->desc);
|
||||
return -1;
|
||||
}
|
||||
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);
|
||||
|
||||
hexdump_buf(stdout, addr, buf, len);
|
||||
fprintf(stdout, "\n");
|
||||
term_out("\n");
|
||||
|
||||
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[]) {
|
||||
if (argc < 4) {
|
||||
terminal_message(MSG_INFO,
|
||||
msg_error(
|
||||
"Usage: write <memory> <addr> <data>[,] {<data>[,]}\n"
|
||||
" write <memory> <addr> <len> <data>[,] {<data>[,]} ...\n"
|
||||
"\n"
|
||||
|
@ -399,14 +404,13 @@ static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
|||
}
|
||||
|
||||
int i;
|
||||
uint8_t write_mode; // Operation mode, "standard" or "fill"
|
||||
uint8_t start_offset; // Which argc argument
|
||||
int len; // Number of bytes to write to memory
|
||||
char *memtype = argv[1]; // Memory name string
|
||||
uint8_t write_mode; // Operation mode, "standard" or "fill"
|
||||
uint8_t start_offset; // Which argc argument
|
||||
int len; // Number of bytes to write to memory
|
||||
char *memtype = argv[1]; // Memory name string
|
||||
AVRMEM *mem = avr_locate_mem(p, memtype);
|
||||
if (mem == NULL) {
|
||||
terminal_message(MSG_INFO, "%s (write): %s memory type not defined for part %s\n",
|
||||
progname, memtype, p->desc);
|
||||
pmsg_error("(write) %s memory type not defined for part %s\n", memtype, p->desc);
|
||||
return -1;
|
||||
}
|
||||
int maxsize = mem->size;
|
||||
|
@ -414,21 +418,19 @@ static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
|||
char *end_ptr;
|
||||
int addr = strtoul(argv[2], &end_ptr, 0);
|
||||
if (*end_ptr || (end_ptr == argv[2])) {
|
||||
terminal_message(MSG_INFO, "%s (write): can't parse address %s\n",
|
||||
progname, argv[2]);
|
||||
pmsg_error("(write) cannot parse address %s\n", argv[2]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
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-1);
|
||||
pmsg_error("(write) %s address 0x%05x is out of range [0, 0x%05x]\n", mem->desc, addr, maxsize-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Allocate a buffer guaranteed to be large enough
|
||||
uint8_t *buf = calloc(mem->size + 8 + maxstrlen(argc-3, argv+3)+1, sizeof(uint8_t));
|
||||
if (buf == NULL) {
|
||||
terminal_message(MSG_INFO, "%s (write): out of memory\n", progname);
|
||||
pmsg_error("(write) out of memory\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -438,8 +440,7 @@ static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
|||
start_offset = 4;
|
||||
len = strtoul(argv[3], &end_ptr, 0);
|
||||
if (*end_ptr || (end_ptr == argv[3])) {
|
||||
terminal_message(MSG_INFO, "%s (write ...): can't parse length %s\n",
|
||||
progname, argv[3]);
|
||||
pmsg_error("(write ...) cannot parse length %s\n", argv[3]);
|
||||
free(buf);
|
||||
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)
|
||||
terminal_message(MSG_INFO, "%s (write): assumption on data types not met? "
|
||||
"Check source and recompile\n", progname);
|
||||
pmsg_error("(write) assumption on data types not met? "
|
||||
"Check source and recompile\n");
|
||||
bool is_big_endian = data.a[7];
|
||||
|
||||
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;
|
||||
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);
|
||||
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)
|
||||
terminal_message(MSG_INFO, "%s (write): %s out of int%d_t range, "
|
||||
"interpreted as %d-byte %lld; consider 'U' suffix\n",
|
||||
progname, argi, data.size*8, data.size, data.ll);
|
||||
pmsg_error("(write) %s out of int%d_t range, "
|
||||
"interpreted as %d-byte %lld; consider 'U' suffix\n", argi, data.size*8, data.size, (long long int) data.ll);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -583,8 +583,8 @@ static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
|||
data.f = strtof(argi, &end_ptr);
|
||||
if (end_ptr != argi && toupper(*end_ptr) == 'F' && end_ptr[1] == 0)
|
||||
data.size = 4;
|
||||
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 (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;
|
||||
}
|
||||
|
@ -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] == '\"')) {
|
||||
char *s = calloc(arglen-1, 1);
|
||||
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);
|
||||
return -1;
|
||||
}
|
||||
// Strip start and end quotes, and unescape C string
|
||||
strncpy(s, argi+1, arglen-2);
|
||||
cfg_unescape(s, s);
|
||||
if (*argi == '\'') { // Single C-style character
|
||||
if (*argi == '\'') { // Single C-style character
|
||||
if(*s && s[1])
|
||||
terminal_message(MSG_INFO, "%s (write): only using first character of %s\n",
|
||||
progname, argi);
|
||||
pmsg_error("(write) only using first character of %s\n", argi);
|
||||
data.ll = *s;
|
||||
data.size = 1;
|
||||
free(s);
|
||||
} else { // C-style string
|
||||
} else { // C-style string
|
||||
data.str_ptr = s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!data.size && !data.str_ptr) {
|
||||
terminal_message(MSG_INFO, "%s (write): can't parse data %s\n",
|
||||
progname, argi);
|
||||
pmsg_error("(write) cannot parse data %s\n", argi);
|
||||
free(buf);
|
||||
return -1;
|
||||
}
|
||||
|
@ -644,8 +642,8 @@ static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
|||
data.bytes_grown = 0;
|
||||
|
||||
if ((addr + len + data.bytes_grown) > maxsize) {
|
||||
terminal_message(MSG_INFO, "%s (write): selected address and # bytes exceed "
|
||||
"range for %s memory\n", progname, memtype);
|
||||
pmsg_error("(write) selected address and # bytes exceed "
|
||||
"range for %s memory\n", memtype);
|
||||
free(buf);
|
||||
return -1;
|
||||
}
|
||||
|
@ -653,11 +651,11 @@ static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
|||
if(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);
|
||||
if (write_mode == WRITE_MODE_FILL)
|
||||
terminal_message(MSG_NOTICE, "; remaining space filled with %s", argv[argc - 2]);
|
||||
terminal_message(MSG_NOTICE, "\n");
|
||||
msg_notice2("; remaining space filled with %s", argv[argc - 2]);
|
||||
msg_notice2("\n");
|
||||
|
||||
pgm->err_led(pgm, OFF);
|
||||
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++) {
|
||||
int rc = pgm->write_byte_cached(pgm, p, mem, addr+i, buf[i]);
|
||||
if (rc) {
|
||||
terminal_message(MSG_INFO, "%s (write): error writing 0x%02x at 0x%05lx, rc=%d\n",
|
||||
progname, buf[i], (long) addr+i, (int) rc);
|
||||
pmsg_error("(write) error writing 0x%02x at 0x%05lx, rc=%d\n", buf[i], (long) addr+i, (int) rc);
|
||||
if (rc == -1)
|
||||
terminal_message(MSG_INFO, "%*swrite operation not supported on memory type %s\n",
|
||||
(int) strlen(progname)+10, "", mem->desc);
|
||||
imsg_error("%*swrite operation not supported on memory type %s\n", 8, "", mem->desc);
|
||||
werror = true;
|
||||
}
|
||||
|
||||
uint8_t b;
|
||||
rc = pgm->read_byte_cached(pgm, p, mem, addr+i, &b);
|
||||
if (b != buf[i]) {
|
||||
terminal_message(MSG_INFO, "%s (write): error writing 0x%02x at 0x%05lx cell=0x%02x\n",
|
||||
progname, buf[i], (long) addr+i, b);
|
||||
pmsg_error("(write) error writing 0x%02x at 0x%05lx cell=0x%02x\n", buf[i], (long) addr+i, b);
|
||||
werror = true;
|
||||
}
|
||||
|
||||
|
@ -713,14 +708,13 @@ static int cmd_send(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
|||
int len;
|
||||
|
||||
if (spi_mode && (pgm->spi == NULL)) {
|
||||
terminal_message(MSG_INFO, "%s (send): the %s programmer does not support direct SPI transfers\n",
|
||||
progname, pgm->type);
|
||||
pmsg_error("(send) the %s programmer does not support direct SPI transfers\n", pgm->type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
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");
|
||||
return -1;
|
||||
|
@ -733,8 +727,7 @@ static int cmd_send(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
|||
for (i=1; i<argc; i++) {
|
||||
cmd[i-1] = strtoul(argv[i], &e, 0);
|
||||
if (*e || (e == argv[i])) {
|
||||
terminal_message(MSG_INFO, "%s (send): can't parse byte %s\n",
|
||||
progname, argv[i]);
|
||||
pmsg_error("(send) cannot parse byte %s\n", argv[i]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -749,19 +742,17 @@ static int cmd_send(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
|||
/*
|
||||
* display results
|
||||
*/
|
||||
terminal_message(MSG_INFO, "results:");
|
||||
term_out("results:");
|
||||
for (i=0; i<len; i++)
|
||||
terminal_message(MSG_INFO, " %02x", res[i]);
|
||||
terminal_message(MSG_INFO, "\n");
|
||||
|
||||
fprintf(stdout, "\n");
|
||||
term_out(" %02x", res[i]);
|
||||
term_out("\n\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
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[]) {
|
||||
if(argc < 3) {
|
||||
terminal_message(MSG_INFO, "Usage: pgerase <memory> <addr>\n");
|
||||
msg_error("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);
|
||||
pmsg_error("(pgerase) %s memory type not defined for part %s\n", 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)));
|
||||
pmsg_error("(pgerase) %s memory cannot be paged addressed by %s\n", memtype, (char *) ldata(lfirst(pgm->id)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -793,21 +782,17 @@ static int cmd_pgerase(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
|||
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]);
|
||||
pmsg_error("(pgerase) cannot parse address %s\n", 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);
|
||||
pmsg_error("(pgerase) %s address 0x%05x is out of range [0, 0x%05x]\n", 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): unable to erase %s page at 0x%05x\n",
|
||||
progname, mem->desc, addr);
|
||||
pmsg_error("(pgerase) unable to erase %s page at 0x%05x\n", mem->desc, addr);
|
||||
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[]) {
|
||||
fprintf(stdout, "\n");
|
||||
term_out("\n");
|
||||
avr_display(stdout, p, "", 0);
|
||||
fprintf(stdout, "\n");
|
||||
term_out("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -831,20 +816,18 @@ static int cmd_sig(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
|||
|
||||
rc = avr_signature(pgm, p);
|
||||
if (rc != 0) {
|
||||
terminal_message(MSG_INFO, "%s (sig): error reading signature data, rc=%d\n",
|
||||
progname, rc);
|
||||
pmsg_error("(sig) error reading signature data, rc=%d\n", rc);
|
||||
}
|
||||
|
||||
m = avr_locate_mem(p, "signature");
|
||||
if (m == NULL) {
|
||||
terminal_message(MSG_INFO, "%s (sig): signature data not defined for device %s\n",
|
||||
progname, p->desc);
|
||||
pmsg_error("(sig) signature data not defined for device %s\n", p->desc);
|
||||
}
|
||||
else {
|
||||
fprintf(stdout, "Device signature = 0x");
|
||||
term_out("Device signature = 0x");
|
||||
for (i=0; i<m->size; i++)
|
||||
fprintf(stdout, "%02x", m->buf[i]);
|
||||
fprintf(stdout, "\n\n");
|
||||
term_out("%02x", m->buf[i]);
|
||||
term_out("\n\n");
|
||||
}
|
||||
|
||||
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[]) {
|
||||
pgm->print_parms(pgm);
|
||||
terminal_message(MSG_INFO, "\n");
|
||||
pgm->print_parms(pgm, stdout);
|
||||
term_out("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -873,18 +856,16 @@ static int cmd_vtarg(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
|||
char *endp;
|
||||
|
||||
if (argc != 2) {
|
||||
terminal_message(MSG_INFO, "Usage: vtarg <value>\n");
|
||||
msg_error("Usage: vtarg <value>\n");
|
||||
return -1;
|
||||
}
|
||||
v = strtod(argv[1], &endp);
|
||||
if (endp == argv[1]) {
|
||||
terminal_message(MSG_INFO, "%s (vtarg): can't parse voltage %s\n",
|
||||
progname, argv[1]);
|
||||
pmsg_error("(vtarg) cannot parse voltage %s\n", argv[1]);
|
||||
return -1;
|
||||
}
|
||||
if ((rc = pgm->set_vtarget(pgm, v)) != 0) {
|
||||
terminal_message(MSG_INFO, "%s (vtarg): unable to set V[target] (rc = %d)\n",
|
||||
progname, rc);
|
||||
pmsg_error("(vtarg) unable to set V[target] (rc = %d)\n", rc);
|
||||
return -3;
|
||||
}
|
||||
return 0;
|
||||
|
@ -897,7 +878,7 @@ static int cmd_fosc(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
|||
char *endp;
|
||||
|
||||
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;
|
||||
}
|
||||
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)
|
||||
v = 0.0;
|
||||
else {
|
||||
terminal_message(MSG_INFO, "%s (fosc): can't parse frequency %s\n",
|
||||
progname, argv[1]);
|
||||
pmsg_error("(fosc) cannot parse frequency %s\n", argv[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')
|
||||
v *= 1e3;
|
||||
if ((rc = pgm->set_fosc(pgm, v)) != 0) {
|
||||
terminal_message(MSG_INFO, "%s (fosc): unable to set oscillator frequency (rc = %d)\n",
|
||||
progname, rc);
|
||||
pmsg_error("(fosc) unable to set oscillator frequency (rc = %d)\n", rc);
|
||||
return -3;
|
||||
}
|
||||
return 0;
|
||||
|
@ -929,19 +908,17 @@ static int cmd_sck(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
|||
char *endp;
|
||||
|
||||
if (argc != 2) {
|
||||
terminal_message(MSG_INFO, "Usage: sck <value>\n");
|
||||
msg_error("Usage: sck <value>\n");
|
||||
return -1;
|
||||
}
|
||||
v = strtod(argv[1], &endp);
|
||||
if (endp == argv[1]) {
|
||||
terminal_message(MSG_INFO, "%s (sck): can't parse period %s\n",
|
||||
progname, argv[1]);
|
||||
pmsg_error("(sck) cannot parse period %s\n", argv[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) {
|
||||
terminal_message(MSG_INFO, "%s (sck): unable to set SCK period (rc = %d)\n",
|
||||
progname, rc);
|
||||
pmsg_error("(sck) unable to set SCK period (rc = %d)\n", rc);
|
||||
return -3;
|
||||
}
|
||||
return 0;
|
||||
|
@ -955,34 +932,30 @@ static int cmd_varef(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
|||
char *endp;
|
||||
|
||||
if (argc != 2 && argc != 3) {
|
||||
terminal_message(MSG_INFO, "Usage: varef [channel] <value>\n");
|
||||
msg_error("Usage: varef [channel] <value>\n");
|
||||
return -1;
|
||||
}
|
||||
if (argc == 2) {
|
||||
chan = 0;
|
||||
v = strtod(argv[1], &endp);
|
||||
if (endp == argv[1]) {
|
||||
terminal_message(MSG_INFO, "%s (varef): can't parse voltage %s\n",
|
||||
progname, argv[1]);
|
||||
pmsg_error("(varef) cannot parse voltage %s\n", argv[1]);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
chan = strtoul(argv[1], &endp, 10);
|
||||
if (endp == argv[1]) {
|
||||
terminal_message(MSG_INFO, "%s (varef): can't parse channel %s\n",
|
||||
progname, argv[1]);
|
||||
pmsg_error("(varef) cannot parse channel %s\n", argv[1]);
|
||||
return -1;
|
||||
}
|
||||
v = strtod(argv[2], &endp);
|
||||
if (endp == argv[2]) {
|
||||
terminal_message(MSG_INFO, "%s (varef): can't parse voltage %s\n",
|
||||
progname, argv[2]);
|
||||
pmsg_error("(varef) cannot parse voltage %s\n", argv[2]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if ((rc = pgm->set_varef(pgm, chan, v)) != 0) {
|
||||
terminal_message(MSG_INFO, "%s (varef): unable to set V[aref] (rc = %d)\n",
|
||||
progname, rc);
|
||||
pmsg_error("(varef) unable to set V[aref] (rc = %d)\n", rc);
|
||||
return -3;
|
||||
}
|
||||
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[]) {
|
||||
int i;
|
||||
|
||||
fprintf(stdout, "Valid commands:\n");
|
||||
term_out("Valid commands:\n");
|
||||
for (i=0; i<NCMDS; i++) {
|
||||
if(!*(void (**)(void)) ((char *) pgm + cmd[i].fnoff))
|
||||
continue;
|
||||
fprintf(stdout, " %-7s : ", cmd[i].name);
|
||||
fprintf(stdout, cmd[i].desc, cmd[i].name);
|
||||
fprintf(stdout, "\n");
|
||||
term_out(" %-7s : ", cmd[i].name);
|
||||
term_out(cmd[i].desc, cmd[i].name);
|
||||
term_out("\n");
|
||||
}
|
||||
fprintf(stdout, "\n"
|
||||
term_out("\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"
|
||||
"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");
|
||||
"read and write access; the cache is synchronised on quit or flush commands.\n"
|
||||
"The part command displays valid memory types for use with dump and write.\n\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1026,26 +999,24 @@ static int cmd_verbose(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
|||
char *endp;
|
||||
|
||||
if (argc != 1 && argc != 2) {
|
||||
terminal_message(MSG_INFO, "Usage: verbose [<value>]\n");
|
||||
msg_error("Usage: verbose [<value>]\n");
|
||||
return -1;
|
||||
}
|
||||
if (argc == 1) {
|
||||
terminal_message(MSG_INFO, "Verbosity level: %d\n", verbose);
|
||||
msg_error("Verbosity level: %d\n", verbose);
|
||||
return 0;
|
||||
}
|
||||
nverb = strtol(argv[1], &endp, 0);
|
||||
if (endp == argv[1] || *endp) {
|
||||
terminal_message(MSG_INFO, "%s (verbose): can't parse verbosity level %s\n",
|
||||
progname, argv[1]);
|
||||
pmsg_error("(verbose) cannot parse verbosity level %s\n", argv[1]);
|
||||
return -1;
|
||||
}
|
||||
if (nverb < 0) {
|
||||
terminal_message(MSG_INFO, "%s: verbosity level must not be negative: %d\n",
|
||||
progname, nverb);
|
||||
pmsg_error("(verbose) level must not be negative: %d\n", nverb);
|
||||
return -1;
|
||||
}
|
||||
verbose = nverb;
|
||||
terminal_message(MSG_INFO, "New verbosity level: %d\n", verbose);
|
||||
term_out("New verbosity level: %d\n", verbose);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1055,26 +1026,24 @@ static int cmd_quell(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
|||
char *endp;
|
||||
|
||||
if (argc != 1 && argc != 2) {
|
||||
terminal_message(MSG_INFO, "Usage: quell [<value>]\n");
|
||||
msg_error("Usage: quell [<value>]\n");
|
||||
return -1;
|
||||
}
|
||||
if (argc == 1) {
|
||||
terminal_message(MSG_INFO, "Quell level: %d\n", quell_progress);
|
||||
msg_error("Quell level: %d\n", quell_progress);
|
||||
return 0;
|
||||
}
|
||||
nquell = strtol(argv[1], &endp, 0);
|
||||
if (endp == argv[1] || *endp) {
|
||||
terminal_message(MSG_INFO, "%s (quell): can't parse quell level %s\n",
|
||||
progname, argv[1]);
|
||||
pmsg_error("(quell) cannot parse quell level %s\n", argv[1]);
|
||||
return -1;
|
||||
}
|
||||
if (nquell < 0) {
|
||||
terminal_message(MSG_INFO, "%s: quell level must not be negative: %d\n",
|
||||
progname, nquell);
|
||||
pmsg_error("(quell) level must not be negative: %d\n", nquell);
|
||||
return -1;
|
||||
}
|
||||
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)
|
||||
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);
|
||||
if (len && strncasecmp(argv[0], cmd[i].name, len)==0) {
|
||||
if (hold != -1) {
|
||||
terminal_message(MSG_INFO, "%s (cmd): command %s is ambiguous\n",
|
||||
progname, argv[0]);
|
||||
pmsg_error("(cmd) command %s is ambiguous\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
hold = i;
|
||||
|
@ -1206,104 +1174,177 @@ static int do_cmd(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
|||
if (hold != -1)
|
||||
return cmd[hold].func(pgm, p, argc, argv);
|
||||
|
||||
terminal_message(MSG_INFO, "%s (cmd): invalid command %s\n",
|
||||
progname, argv[0]);
|
||||
pmsg_error("(cmd) invalid command %s\n", argv[0]);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
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];
|
||||
fprintf(stdout, "%s", prompt);
|
||||
if (fgets(input, sizeof(input), stdin))
|
||||
{
|
||||
/* FIXME: readline strips the '\n', should this too? */
|
||||
return strdup(input);
|
||||
|
||||
term_out("%s", prompt);
|
||||
if(fgets(input, sizeof(input), stdin)) {
|
||||
int len = strlen(input);
|
||||
if(len > 0 && input[len-1] == '\n')
|
||||
input[len-1] = 0;
|
||||
return cfg_strdup(__func__, input);
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int terminal_mode(PROGRAMMER *pgm, AVRPART *p) {
|
||||
char *cmdbuf;
|
||||
char *q;
|
||||
int rc;
|
||||
int argc;
|
||||
char **argv;
|
||||
static int process_line(char *cmdbuf, PROGRAMMER *pgm, struct avrpart *p) {
|
||||
int argc, rc;
|
||||
char **argv = NULL, *q;
|
||||
|
||||
rc = 0;
|
||||
while ((cmdbuf = terminal_get_input("avrdude> ")) != NULL) {
|
||||
/*
|
||||
* find the start of the command, skipping any white space
|
||||
*/
|
||||
q = cmdbuf;
|
||||
while (*q && isspace((unsigned char) *q))
|
||||
q++;
|
||||
// Find the start of the command, skipping any white space
|
||||
q = cmdbuf;
|
||||
while(*q && isspace((unsigned char) *q))
|
||||
q++;
|
||||
|
||||
/* skip blank lines and comments */
|
||||
if (!*q || (*q == '#'))
|
||||
continue;
|
||||
// Skip blank lines and comments
|
||||
if (!*q || (*q == '#'))
|
||||
return 0;
|
||||
|
||||
/* tokenize command line */
|
||||
argc = tokenize(q, &argv);
|
||||
if (argc < 0) {
|
||||
free(cmdbuf);
|
||||
return argc;
|
||||
}
|
||||
// Tokenize command line
|
||||
argc = tokenize(q, &argv);
|
||||
|
||||
if(!argv)
|
||||
return -1;
|
||||
|
||||
#if !defined(HAVE_LIBREADLINE) || defined(WIN32) || defined(__APPLE__)
|
||||
fprintf(stdout, ">>> ");
|
||||
term_out(">>> ");
|
||||
for (int i=0; i<argc; i++)
|
||||
fprintf(stdout, "%s ", argv[i]);
|
||||
fprintf(stdout, "\n");
|
||||
term_out("%s ", argv[i]);
|
||||
term_out("\n");
|
||||
#endif
|
||||
|
||||
/* run the command */
|
||||
rc = do_cmd(pgm, p, argc, argv);
|
||||
free(argv);
|
||||
if (rc > 0) {
|
||||
rc = 0;
|
||||
break;
|
||||
// Run the command
|
||||
rc = do_cmd(pgm, p, argc, argv);
|
||||
free(argv);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#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;
|
||||
va_list ap;
|
||||
|
||||
fflush(stdout); fflush(stderr);
|
||||
if (verbose >= msglvl) {
|
||||
va_start(ap, format);
|
||||
rc = vfprintf(stderr, format, ap);
|
||||
va_end(ap);
|
||||
while((cmdbuf = terminal_get_input("avrdude> "))) {
|
||||
int rc = process_line(cmdbuf, pgm, p);
|
||||
free(cmdbuf);
|
||||
if(rc > 0)
|
||||
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 char *header;
|
||||
static int last, done;
|
||||
static int last, done = 1;
|
||||
int i;
|
||||
|
||||
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[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(finish)
|
||||
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 int last, done;
|
||||
static int last, done = 1;
|
||||
|
||||
setvbuf(stderr, (char *) NULL, _IONBF, 0);
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@ typedef enum {
|
|||
int terminal_mode(PROGRAMMER * pgm, struct avrpart * p);
|
||||
char * terminal_get_input(const char *prompt);
|
||||
void terminal_setup_update_progress();
|
||||
int terminal_message(const int msglvl, const char *format, ...);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
15
src/update.c
15
src/update.c
|
@ -335,11 +335,11 @@ int update_is_readable(const char *fn) {
|
|||
static void ioerror(const char *iotype, UPDATE *upd) {
|
||||
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)
|
||||
msg_ext_error("memstats(): %s", strerror(errnocp));
|
||||
msg_ext_error("%s", strerror(errnocp));
|
||||
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");
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
report_progress(0, 1, "Reading");
|
||||
if(mem->size > 32 || verbose > 1)
|
||||
report_progress(0, 1, "Reading");
|
||||
|
||||
rc = avr_read(pgm, p, upd->memtype, 0);
|
||||
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);
|
||||
|
||||
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);
|
||||
report_progress(1, 1, NULL);
|
||||
} 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);
|
||||
}
|
||||
|
||||
report_progress (0,1,"Reading");
|
||||
if(mem->size > 32 || verbose > 1)
|
||||
report_progress (0,1,"Reading");
|
||||
rc = avr_read(pgm, p, upd->memtype, v);
|
||||
report_progress (1,1,NULL);
|
||||
if (rc < 0) {
|
||||
|
|
250
src/usb_hidapi.c
250
src/usb_hidapi.c
|
@ -65,78 +65,70 @@ static int usbhid_open(const char *port, union pinfo pinfo, union filedescriptor
|
|||
* right-to-left, so only the least significant nibbles need to be
|
||||
* specified.
|
||||
*/
|
||||
if ((serno = strchr(port, ':')) != NULL)
|
||||
{
|
||||
/* first, drop all colons there if any */
|
||||
cp2 = ++serno;
|
||||
if ((serno = strchr(port, ':')) != NULL) {
|
||||
/* First, drop all colons there if any */
|
||||
cp2 = ++serno;
|
||||
|
||||
while ((cp2 = strchr(cp2, ':')) != NULL)
|
||||
{
|
||||
x = strlen(cp2) - 1;
|
||||
memmove(cp2, cp2 + 1, x);
|
||||
cp2[x] = '\0';
|
||||
}
|
||||
while ((cp2 = strchr(cp2, ':')) != NULL) {
|
||||
x = strlen(cp2) - 1;
|
||||
memmove(cp2, cp2 + 1, x);
|
||||
cp2[x] = '\0';
|
||||
}
|
||||
|
||||
if (strlen(serno) > 12)
|
||||
{
|
||||
pmsg_error("invalid serial number %s\n", serno);
|
||||
return -1;
|
||||
}
|
||||
if (strlen(serno) > 12) {
|
||||
pmsg_error("invalid serial number %s\n", serno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
wchar_t wserno[15];
|
||||
mbstowcs(wserno, serno, 15);
|
||||
size_t serlen = strlen(serno);
|
||||
wchar_t wserno[15];
|
||||
mbstowcs(wserno, serno, 15);
|
||||
size_t serlen = strlen(serno);
|
||||
|
||||
/*
|
||||
* Now, try finding all devices matching VID:PID, and compare
|
||||
* their serial numbers against the requested one.
|
||||
*/
|
||||
struct hid_device_info *list, *walk;
|
||||
list = hid_enumerate(pinfo.usbinfo.vid, pinfo.usbinfo.pid);
|
||||
if (list == NULL)
|
||||
return -1;
|
||||
/*
|
||||
* Now, try finding all devices matching VID:PID, and compare
|
||||
* their serial numbers against the requested one.
|
||||
*/
|
||||
struct hid_device_info *list, *walk;
|
||||
list = hid_enumerate(pinfo.usbinfo.vid, pinfo.usbinfo.pid);
|
||||
if (list == NULL) {
|
||||
pmsg_error("No USB HID devices found\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
walk = list;
|
||||
while (walk)
|
||||
walk = list;
|
||||
while (walk) {
|
||||
pmsg_notice("usbhid_open(): found %ls, serno: %ls\n", walk->product_string, walk->serial_number);
|
||||
size_t slen = wcslen(walk->serial_number);
|
||||
if (slen >= serlen && wcscmp(walk->serial_number + slen - serlen, wserno) == 0)
|
||||
{
|
||||
pmsg_notice("usbhid_open(): found %ls, serno: %ls\n", walk->product_string, walk->serial_number);
|
||||
size_t slen = wcslen(walk->serial_number);
|
||||
if (slen >= serlen &&
|
||||
wcscmp(walk->serial_number + slen - serlen, wserno) == 0)
|
||||
{
|
||||
/* found matching serial number */
|
||||
break;
|
||||
}
|
||||
pmsg_debug("usbhid_open(): serial number does not match\n");
|
||||
walk = walk->next;
|
||||
/* Found matching serial number */
|
||||
break;
|
||||
}
|
||||
if (walk == NULL)
|
||||
{
|
||||
pmsg_error("no matching device found\n");
|
||||
hid_free_enumeration(list);
|
||||
return -1;
|
||||
}
|
||||
pmsg_debug("usbhid_open(): opening path %s\n", walk->path);
|
||||
dev = hid_open_path(walk->path);
|
||||
pmsg_debug("usbhid_open(): serial number does not match\n");
|
||||
walk = walk->next;
|
||||
}
|
||||
if (walk == NULL) {
|
||||
pmsg_error("no matching device found\n");
|
||||
hid_free_enumeration(list);
|
||||
if (dev == NULL)
|
||||
{
|
||||
pmsg_error("found device, but hid_open_path() failed\n");
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
pmsg_debug("usbhid_open(): opening path %s\n", walk->path);
|
||||
dev = hid_open_path(walk->path);
|
||||
hid_free_enumeration(list);
|
||||
if (dev == NULL) {
|
||||
pmsg_error("found device, but hid_open_path() failed\n");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
/* No serial number requested, pass straight to hid_open() */
|
||||
dev = hid_open(pinfo.usbinfo.vid, pinfo.usbinfo.pid, NULL);
|
||||
if (dev == NULL)
|
||||
{
|
||||
/*
|
||||
* No serial number requested, pass straight to hid_open()
|
||||
*/
|
||||
dev = hid_open(pinfo.usbinfo.vid, pinfo.usbinfo.pid, NULL);
|
||||
if (dev == NULL)
|
||||
{
|
||||
pmsg_error("no device found\n");
|
||||
return -1;
|
||||
}
|
||||
pmsg_warning("USB device with VID: 0x%04x and PID: 0x%04x not found\n",
|
||||
pinfo.usbinfo.vid, pinfo.usbinfo.pid);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
fd->usb.handle = dev;
|
||||
|
||||
|
@ -166,39 +158,38 @@ static int usbhid_open(const char *port, union pinfo pinfo, union filedescriptor
|
|||
* be incremented by one, as the report ID will be omitted by the
|
||||
* hidapi library.
|
||||
*/
|
||||
if (pinfo.usbinfo.vid == USB_VENDOR_ATMEL)
|
||||
{
|
||||
pmsg_debug("usbhid_open(): probing for max packet size\n");
|
||||
memset(usbbuf, 0, sizeof usbbuf);
|
||||
usbbuf[0] = 0; /* no HID reports used */
|
||||
usbbuf[1] = 0; /* DAP_Info */
|
||||
usbbuf[2] = 0xFF; /* get max. packet size */
|
||||
if (pinfo.usbinfo.vid == USB_VENDOR_ATMEL) {
|
||||
pmsg_debug("usbhid_open(): probing for max packet size\n");
|
||||
memset(usbbuf, 0, sizeof usbbuf);
|
||||
usbbuf[0] = 0; /* no HID reports used */
|
||||
usbbuf[1] = 0; /* DAP_Info */
|
||||
usbbuf[2] = 0xFF; /* get max. packet size */
|
||||
|
||||
hid_write(dev, usbbuf, 65);
|
||||
fd->usb.max_xfer = 64; /* first guess */
|
||||
hid_write(dev, usbbuf, 65);
|
||||
fd->usb.max_xfer = 64; /* first guess */
|
||||
|
||||
memset(usbbuf, 0, sizeof usbbuf);
|
||||
int res = hid_read_timeout(dev, usbbuf, 10 /* bytes */, 50 /* milliseconds */);
|
||||
if (res == 0) {
|
||||
/* no timely response, assume 512 byte size */
|
||||
hid_write(dev, usbbuf, (512 - 64) + 1);
|
||||
fd->usb.max_xfer = 512;
|
||||
res = hid_read_timeout(dev, usbbuf, 10, 50);
|
||||
}
|
||||
if (res <= 0) {
|
||||
pmsg_error("no response from device\n");
|
||||
hid_close(dev);
|
||||
return -1;
|
||||
}
|
||||
if (usbbuf[0] != 0 || usbbuf[1] != 2) {
|
||||
pmsg_error("unexpected reply to DAP_Info: 0x%02x 0x%02x\n",
|
||||
usbbuf[0], usbbuf[1]);
|
||||
} else {
|
||||
fd->usb.max_xfer = usbbuf[2] + (usbbuf[3] << 8);
|
||||
pmsg_debug("usbhid_open(): setting max_xfer from DAP_Info response to %d\n",
|
||||
fd->usb.max_xfer);
|
||||
}
|
||||
memset(usbbuf, 0, sizeof usbbuf);
|
||||
int res = hid_read_timeout(dev, usbbuf, 10 /* bytes */, 50 /* milliseconds */);
|
||||
if (res == 0) {
|
||||
/* No timely response, assume 512 byte size */
|
||||
hid_write(dev, usbbuf, (512 - 64) + 1);
|
||||
fd->usb.max_xfer = 512;
|
||||
res = hid_read_timeout(dev, usbbuf, 10, 50);
|
||||
}
|
||||
if (res <= 0) {
|
||||
pmsg_error("no response from device\n");
|
||||
hid_close(dev);
|
||||
return -1;
|
||||
}
|
||||
if (usbbuf[0] != 0 || usbbuf[1] != 2) {
|
||||
pmsg_error("unexpected reply to DAP_Info: 0x%02x 0x%02x\n",
|
||||
usbbuf[0], usbbuf[1]);
|
||||
} else {
|
||||
fd->usb.max_xfer = usbbuf[2] + (usbbuf[3] << 8);
|
||||
pmsg_debug("usbhid_open(): setting max_xfer from DAP_Info response to %d\n",
|
||||
fd->usb.max_xfer);
|
||||
}
|
||||
}
|
||||
if (fd->usb.max_xfer > USBDEV_MAX_XFER_3) {
|
||||
pmsg_error("unexpected max size %d, reducing to %d\n",
|
||||
fd->usb.max_xfer, USBDEV_MAX_XFER_3);
|
||||
|
@ -208,8 +199,7 @@ static int usbhid_open(const char *port, union pinfo pinfo, union filedescriptor
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void usbhid_close(union filedescriptor *fd)
|
||||
{
|
||||
static void usbhid_close(union filedescriptor *fd) {
|
||||
hid_device *udev = (hid_device *)fd->usb.handle;
|
||||
|
||||
if (udev == NULL)
|
||||
|
@ -219,22 +209,20 @@ static void usbhid_close(union filedescriptor *fd)
|
|||
}
|
||||
|
||||
|
||||
static int usbhid_send(const union filedescriptor *fd, const unsigned char *bp, size_t mlen)
|
||||
{
|
||||
static int usbhid_send(const union filedescriptor *fd, const unsigned char *bp, size_t mlen) {
|
||||
hid_device *udev = (hid_device *)fd->usb.handle;
|
||||
int rv;
|
||||
int i = mlen;
|
||||
const unsigned char * p = bp;
|
||||
unsigned char usbbuf[USBDEV_MAX_XFER_3 + 1];
|
||||
|
||||
|
||||
int tx_size;
|
||||
|
||||
if (udev == NULL)
|
||||
return -1;
|
||||
|
||||
tx_size = (mlen < USBDEV_MAX_XFER_3)? mlen: USBDEV_MAX_XFER_3;
|
||||
usbbuf[0] = 0; /* no report ID used */
|
||||
usbbuf[0] = 0; /* No report ID used */
|
||||
memcpy(usbbuf + 1, bp, tx_size);
|
||||
rv = hid_write(udev, usbbuf, tx_size + 1);
|
||||
if (rv < 0) {
|
||||
|
@ -244,30 +232,26 @@ static int usbhid_send(const union filedescriptor *fd, const unsigned char *bp,
|
|||
if (rv != tx_size + 1)
|
||||
pmsg_error("short write to USB: %d bytes out of %d written\n", rv, tx_size + 1);
|
||||
|
||||
if (verbose > 4)
|
||||
{
|
||||
pmsg_trace2("sent: ");
|
||||
if (verbose > 4) {
|
||||
pmsg_trace2("sent: ");
|
||||
|
||||
while (i) {
|
||||
unsigned char c = *p;
|
||||
if (isprint(c)) {
|
||||
msg_trace2("%c ", c);
|
||||
}
|
||||
else {
|
||||
msg_trace2(". ");
|
||||
}
|
||||
msg_trace2("[%02x] ", c);
|
||||
while (i) {
|
||||
unsigned char c = *p;
|
||||
if (isprint(c))
|
||||
msg_trace2("%c ", c);
|
||||
else
|
||||
msg_trace2(". ");
|
||||
msg_trace2("[%02x] ", c);
|
||||
|
||||
p++;
|
||||
i--;
|
||||
}
|
||||
msg_trace2("\n");
|
||||
p++;
|
||||
i--;
|
||||
}
|
||||
msg_trace2("\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usbhid_recv(const union filedescriptor *fd, unsigned char *buf, size_t nbytes)
|
||||
{
|
||||
static int usbhid_recv(const union filedescriptor *fd, unsigned char *buf, size_t nbytes) {
|
||||
hid_device *udev = (hid_device *)fd->usb.handle;
|
||||
int i, rv;
|
||||
unsigned char * p = buf;
|
||||
|
@ -279,31 +263,26 @@ static int usbhid_recv(const union filedescriptor *fd, unsigned char *buf, size_
|
|||
if (i != nbytes)
|
||||
pmsg_error("short read, read only %d out of %lu bytes\n", i, (unsigned long) nbytes);
|
||||
|
||||
if (verbose > 4)
|
||||
{
|
||||
pmsg_trace2("recv: ");
|
||||
if (verbose > 4) {
|
||||
pmsg_trace2("recv: ");
|
||||
|
||||
while (i) {
|
||||
unsigned char c = *p;
|
||||
if (isprint(c)) {
|
||||
msg_trace2("%c ", c);
|
||||
}
|
||||
else {
|
||||
msg_trace2(". ");
|
||||
}
|
||||
msg_trace2("[%02x] ", c);
|
||||
while (i) {
|
||||
unsigned char c = *p;
|
||||
if (isprint(c))
|
||||
msg_trace2("%c ", c);
|
||||
else
|
||||
msg_trace2(". ");
|
||||
msg_trace2("[%02x] ", c);
|
||||
|
||||
p++;
|
||||
i--;
|
||||
}
|
||||
msg_trace2("\n");
|
||||
p++;
|
||||
i--;
|
||||
}
|
||||
msg_trace2("\n");
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int usbhid_drain(const union filedescriptor *fd, int display)
|
||||
{
|
||||
static int usbhid_drain(const union filedescriptor *fd, int display) {
|
||||
/*
|
||||
* There is not much point in trying to flush any data
|
||||
* on an USB endpoint, as the endpoint is supposed to
|
||||
|
@ -321,8 +300,7 @@ static int usbhid_drain(const union filedescriptor *fd, int display)
|
|||
/*
|
||||
* Device descriptor.
|
||||
*/
|
||||
struct serial_device usbhid_serdev =
|
||||
{
|
||||
struct serial_device usbhid_serdev = {
|
||||
.open = usbhid_open,
|
||||
.close = usbhid_close,
|
||||
.send = usbhid_send,
|
||||
|
|
|
@ -25,19 +25,28 @@
|
|||
#ifndef usbdevs_h
|
||||
#define usbdevs_h
|
||||
|
||||
#define USB_VENDOR_ATMEL 1003
|
||||
#define USB_DEVICE_JTAGICEMKII 0x2103
|
||||
#define USB_DEVICE_AVRISPMKII 0x2104
|
||||
#define USB_DEVICE_STK600 0x2106
|
||||
#define USB_DEVICE_AVRDRAGON 0x2107
|
||||
#define USB_DEVICE_JTAGICE3 0x2110
|
||||
#define USB_DEVICE_XPLAINEDPRO 0x2111
|
||||
#define USB_DEVICE_JTAG3_EDBG 0x2140
|
||||
#define USB_DEVICE_ATMEL_ICE 0x2141
|
||||
#define USB_VENDOR_ATMEL 0x03EB
|
||||
#define USB_VENDOR_MICROCHIP 0x04D8
|
||||
|
||||
#define USB_VENDOR_FTDI 0x0403
|
||||
#define USB_DEVICE_FT2232 0x6010
|
||||
#define USB_DEVICE_FT245 0x6001
|
||||
#define USB_DEVICE_JTAGICEMKII 0x2103
|
||||
#define USB_DEVICE_AVRISPMKII 0x2104
|
||||
#define USB_DEVICE_STK600 0x2106
|
||||
#define USB_DEVICE_AVRDRAGON 0x2107
|
||||
#define USB_DEVICE_JTAGICE3 0x2110
|
||||
#define USB_DEVICE_XPLAINEDPRO 0x2111
|
||||
#define USB_DEVICE_JTAG3_EDBG 0x2140
|
||||
#define USB_DEVICE_ATMEL_ICE 0x2141
|
||||
#define USB_DEVICE_POWERDEBUGGER 0x2144
|
||||
#define USB_DEVICE_XPLAINEDMINI 0x2145
|
||||
#define USB_DEVICE_PKOBN 0x2175
|
||||
#define USB_DEVICE_PICKIT4_AVR_MODE 0x2177
|
||||
#define USB_DEVICE_PICKIT4_PIC_MODE 0x9012
|
||||
#define USB_DEVICE_SNAP_AVR_MODE 0x2180
|
||||
#define USB_DEVICE_SNAP_PIC_MODE 0x9018
|
||||
|
||||
#define USB_VENDOR_FTDI 0x0403
|
||||
#define USB_DEVICE_FT2232 0x6010
|
||||
#define USB_DEVICE_FT245 0x6001
|
||||
|
||||
#define USBASP_SHARED_VID 0x16C0 /* VOTI */
|
||||
#define USBASP_SHARED_PID 0x05DC /* Obdev's free shared PID */
|
||||
|
|
Loading…
Reference in New Issue