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
|
libusb-1.0-0-dev
|
||||||
libhidapi-dev
|
libhidapi-dev
|
||||||
libftdi1-dev
|
libftdi1-dev
|
||||||
|
libreadline-dev
|
||||||
texinfo
|
texinfo
|
||||||
texlive
|
texlive
|
||||||
texi2html
|
texi2html
|
||||||
|
@ -110,6 +111,7 @@ jobs:
|
||||||
libusb-1.0-0-dev:${{matrix.arch}}
|
libusb-1.0-0-dev:${{matrix.arch}}
|
||||||
libhidapi-dev:${{matrix.arch}}
|
libhidapi-dev:${{matrix.arch}}
|
||||||
libftdi1-dev:${{matrix.arch}}
|
libftdi1-dev:${{matrix.arch}}
|
||||||
|
libreadline-dev:${{matrix.arch}}
|
||||||
- name: Configure
|
- name: Configure
|
||||||
run: >-
|
run: >-
|
||||||
cmake
|
cmake
|
||||||
|
|
16
NEWS
16
NEWS
|
@ -58,6 +58,12 @@ Changes since version 7.0:
|
||||||
- Make UPDI programmers less verbose during initialization
|
- Make UPDI programmers less verbose during initialization
|
||||||
#1084
|
#1084
|
||||||
- Quell mode isn't handled systematically #1114
|
- 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:
|
* Pull requests:
|
||||||
|
|
||||||
|
@ -153,6 +159,16 @@ Changes since version 7.0:
|
||||||
- Suppress Teensy USB communication error message on reboot #1122
|
- Suppress Teensy USB communication error message on reboot #1122
|
||||||
- Fix UPDI erase when target is locked #1125
|
- Fix UPDI erase when target is locked #1125
|
||||||
- Review and overhaul AVRDUDE's messaging system #1126
|
- 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:
|
* Internals:
|
||||||
|
|
||||||
|
|
4
build.sh
4
build.sh
|
@ -53,9 +53,9 @@ case "${ostype}" in
|
||||||
# Apple M1 (may be new version of homebrew also)
|
# Apple M1 (may be new version of homebrew also)
|
||||||
if [ -d /opt/homebrew ]
|
if [ -d /opt/homebrew ]
|
||||||
then
|
then
|
||||||
build_flags="${build_flags} -D CMAKE_C_FLAGS=-I/opt/homebrew/include -D CMAKE_EXE_LINKER_FLAGS=-L/opt/homebrew/Cellar"
|
build_flags="${build_flags} -D CMAKE_C_FLAGS=-I/opt/homebrew/include -D CMAKE_EXE_LINKER_FLAGS=-L/opt/homebrew/Cellar -D HAVE_LIBREADLINE:FILEPATH=/opt/homebrew/lib/libreadline.dylib"
|
||||||
else
|
else
|
||||||
build_flags="${build_flags} -D CMAKE_C_FLAGS=-I/usr/local/include -D CMAKE_EXE_LINKER_FLAGS=-L/usr/local/Cellar"
|
build_flags="${build_flags} -D CMAKE_C_FLAGS=-I/usr/local/include -D CMAKE_EXE_LINKER_FLAGS=-L/usr/local/Cellar -D HAVE_LIBREADLINE:FILEPATH=/usr/local/lib/libreadline.dylib"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
|
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);
|
return avr_mem_hiaddr(mem);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pgm->paged_load != NULL && mem->page_size > 1 &&
|
// HW programmers need a page size > 1, bootloader typ only offer paged r/w
|
||||||
mem->size % mem->page_size == 0) {
|
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
|
* 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;
|
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
|
* 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 avr_signature(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
report_progress (0,1,"Reading");
|
if(verbose > 1)
|
||||||
|
report_progress(0, 1, "Reading");
|
||||||
rc = avr_read(pgm, p, "signature", 0);
|
rc = avr_read(pgm, p, "signature", 0);
|
||||||
if (rc < LIBAVRDUDE_SUCCESS) {
|
if (rc < LIBAVRDUDE_SUCCESS) {
|
||||||
pmsg_error("unable to read signature data for part %s, rc=%d\n", p->desc, rc);
|
pmsg_error("unable to read signature data for part %s, rc=%d\n", p->desc, rc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
report_progress (1,1,NULL);
|
report_progress(1, 1, NULL);
|
||||||
|
|
||||||
return LIBAVRDUDE_SUCCESS;
|
return LIBAVRDUDE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,6 +126,9 @@ int avr_has_paged_access(const PROGRAMMER *pgm, const AVRMEM *mem) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define fallback_read_byte (pgm->read_byte != avr_read_byte_cached? pgm->read_byte: avr_read_byte_default)
|
||||||
|
#define fallback_write_byte (pgm->write_byte != avr_write_byte_cached? pgm->write_byte: avr_write_byte_default)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read the page containing addr from the device into buf
|
* Read the page containing addr from the device into buf
|
||||||
* - Caller to ensure buf has mem->page_size bytes
|
* - Caller to ensure buf has mem->page_size bytes
|
||||||
|
@ -141,14 +144,14 @@ int avr_read_page_default(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM
|
||||||
unsigned char *pagecopy = cfg_malloc("avr_read_page_default()", pgsize);
|
unsigned char *pagecopy = cfg_malloc("avr_read_page_default()", pgsize);
|
||||||
|
|
||||||
if(pgsize == 1)
|
if(pgsize == 1)
|
||||||
return pgm->read_byte(pgm, p, mem, addr, buf);
|
return fallback_read_byte(pgm, p, mem, addr, buf);
|
||||||
|
|
||||||
memcpy(pagecopy, mem->buf + base, pgsize);
|
memcpy(pagecopy, mem->buf + base, pgsize);
|
||||||
if((rc = pgm->paged_load(pgm, p, mem, pgsize, base, pgsize)) >= 0)
|
if((rc = pgm->paged_load(pgm, p, mem, pgsize, base, pgsize)) >= 0)
|
||||||
memcpy(buf, mem->buf + base, pgsize);
|
memcpy(buf, mem->buf + base, pgsize);
|
||||||
memcpy(mem->buf + base, pagecopy, pgsize);
|
memcpy(mem->buf + base, pagecopy, pgsize);
|
||||||
|
|
||||||
if(rc < 0) {
|
if(rc < 0 && pgm->read_byte != avr_read_byte_cached) {
|
||||||
rc = LIBAVRDUDE_SUCCESS;
|
rc = LIBAVRDUDE_SUCCESS;
|
||||||
for(int i=0; i<pgsize; i++) {
|
for(int i=0; i<pgsize; i++) {
|
||||||
if(pgm->read_byte(pgm, p, mem, base+i, pagecopy+i) < 0) {
|
if(pgm->read_byte(pgm, p, mem, base+i, pagecopy+i) < 0) {
|
||||||
|
@ -179,7 +182,7 @@ int avr_write_page_default(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM
|
||||||
unsigned char *pagecopy = cfg_malloc("avr_write_page_default()", pgsize);
|
unsigned char *pagecopy = cfg_malloc("avr_write_page_default()", pgsize);
|
||||||
|
|
||||||
if(pgsize == 1)
|
if(pgsize == 1)
|
||||||
return pgm->write_byte(pgm, p, mem, addr, *data);
|
return fallback_write_byte(pgm, p, mem, addr, *data);
|
||||||
|
|
||||||
memcpy(pagecopy, mem->buf + base, pgsize);
|
memcpy(pagecopy, mem->buf + base, pgsize);
|
||||||
memcpy(mem->buf + base, data, pgsize);
|
memcpy(mem->buf + base, data, pgsize);
|
||||||
|
@ -261,18 +264,25 @@ static int loadCachePage(AVR_Cache *cp, const PROGRAMMER *pgm, const AVRPART *p,
|
||||||
static int writeCachePage(AVR_Cache *cp, const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, int base, int nlOnErr) {
|
static int writeCachePage(AVR_Cache *cp, const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, int base, int nlOnErr) {
|
||||||
// Write modified page cont to device; if unsuccessful try bytewise access
|
// Write modified page cont to device; if unsuccessful try bytewise access
|
||||||
if(avr_write_page_default(pgm, p, mem, base, cp->cont + base) < 0) {
|
if(avr_write_page_default(pgm, p, mem, base, cp->cont + base) < 0) {
|
||||||
for(int i=0; i < cp->page_size; i++)
|
if(pgm->read_byte != avr_read_byte_cached && pgm->write_byte != avr_write_byte_cached) {
|
||||||
if(cp->cont[base+i] != cp->copy[base+i])
|
for(int i=0; i < cp->page_size; i++)
|
||||||
if(pgm->write_byte(pgm, p, mem, base+i, cp->cont[base+i]) < 0 ||
|
if(cp->cont[base+i] != cp->copy[base+i])
|
||||||
pgm->read_byte(pgm, p, mem, base+i, cp->copy+base+i) < 0) {
|
if(pgm->write_byte(pgm, p, mem, base+i, cp->cont[base+i]) < 0 ||
|
||||||
report_progress(1, -1, NULL);
|
pgm->read_byte(pgm, p, mem, base+i, cp->copy+base+i) < 0) {
|
||||||
if(nlOnErr && quell_progress)
|
report_progress(1, -1, NULL);
|
||||||
msg_info("\n");
|
if(nlOnErr && quell_progress)
|
||||||
pmsg_error("writeCachePage() %s access error at addr 0x%04x\n", mem->desc, base+i);
|
msg_info("\n");
|
||||||
return LIBAVRDUDE_GENERAL_FAILURE;
|
pmsg_error("%s access error at addr 0x%04x\n", mem->desc, base+i);
|
||||||
}
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
return LIBAVRDUDE_SUCCESS; // Bytewise writes & reads successful
|
return LIBAVRDUDE_SUCCESS; // Bytewise writes & reads successful
|
||||||
|
}
|
||||||
|
report_progress(1, -1, NULL);
|
||||||
|
if(nlOnErr && quell_progress)
|
||||||
|
msg_info("\n");
|
||||||
|
pmsg_error("write %s page error at addr 0x%04x\n", mem->desc, base);
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
}
|
}
|
||||||
// Read page back from device and update copy to what is on device
|
// Read page back from device and update copy to what is on device
|
||||||
if(avr_read_page_default(pgm, p, mem, base, cp->copy + base) < 0) {
|
if(avr_read_page_default(pgm, p, mem, base, cp->copy + base) < 0) {
|
||||||
|
@ -552,7 +562,7 @@ int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *
|
||||||
|
|
||||||
// Use pgm->read_byte() if not EEPROM/flash or no paged access
|
// Use pgm->read_byte() if not EEPROM/flash or no paged access
|
||||||
if(!avr_has_paged_access(pgm, mem))
|
if(!avr_has_paged_access(pgm, mem))
|
||||||
return pgm->read_byte(pgm, p, mem, addr, value);
|
return fallback_read_byte(pgm, p, mem, addr, value);
|
||||||
|
|
||||||
// If address is out of range synchronise cache and, if successful, pretend reading a zero
|
// If address is out of range synchronise cache and, if successful, pretend reading a zero
|
||||||
if(addr >= (unsigned long) mem->size) {
|
if(addr >= (unsigned long) mem->size) {
|
||||||
|
@ -592,9 +602,9 @@ int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *
|
||||||
int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
|
int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
|
||||||
unsigned long addr, unsigned char data) {
|
unsigned long addr, unsigned char data) {
|
||||||
|
|
||||||
// Use pgm->read_byte() if not EEPROM/flash or no paged access
|
// Use pgm->write_byte() if not EEPROM/flash or no paged access
|
||||||
if(!avr_has_paged_access(pgm, mem))
|
if(!avr_has_paged_access(pgm, mem))
|
||||||
return pgm->write_byte(pgm, p, mem, addr, data);
|
return fallback_write_byte(pgm, p, mem, addr, data);
|
||||||
|
|
||||||
// If address is out of range synchronise caches with device and return whether successful
|
// If address is out of range synchronise caches with device and return whether successful
|
||||||
if(addr >= (unsigned long) mem->size)
|
if(addr >= (unsigned long) mem->size)
|
||||||
|
@ -687,7 +697,7 @@ int avr_page_erase_cached(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM
|
||||||
return LIBAVRDUDE_GENERAL_FAILURE;
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
|
||||||
if(mem->page_size == 1) {
|
if(mem->page_size == 1) {
|
||||||
if(pgm->write_byte(pgm, p, mem, uaddr, 0xff) < 0)
|
if(fallback_write_byte(pgm, p, mem, uaddr, 0xff) < 0)
|
||||||
return LIBAVRDUDE_GENERAL_FAILURE;
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
} else {
|
} else {
|
||||||
if(!pgm->page_erase || pgm->page_erase(pgm, p, mem, uaddr) < 0)
|
if(!pgm->page_erase || pgm->page_erase(pgm, p, mem, uaddr) < 0)
|
||||||
|
|
|
@ -332,18 +332,20 @@ programmed in high-voltage serial mode.
|
||||||
Override the RS-232 connection baud rate specified in the respective
|
Override the RS-232 connection baud rate specified in the respective
|
||||||
programmer's entry of the configuration file.
|
programmer's entry of the configuration file.
|
||||||
.It Fl B Ar bitclock
|
.It Fl B Ar bitclock
|
||||||
Specify the bit clock period for the JTAG interface or the ISP clock (JTAG ICE only).
|
Specify the bit clock period for the JTAG, PDI, TPI, UPDI, or ISP
|
||||||
The value is a floating-point number in microseconds.
|
interface. The value is a floating-point number in microseconds.
|
||||||
Alternatively, the value might be suffixed with "Hz", "kHz", or "MHz",
|
Alternatively, the value might be suffixed with "Hz", "kHz" or
|
||||||
in order to specify the bit clock frequency, rather than a period.
|
"MHz" in order to specify the bit clock frequency rather than a
|
||||||
The default value of the JTAG ICE results in about 1 microsecond bit
|
period. Some programmers default their bit clock value to a 1
|
||||||
clock period, suitable for target MCUs running at 4 MHz clock and
|
microsecond bit clock period, suitable for target MCUs running at 4
|
||||||
above.
|
MHz clock and above. Slower MCUs need a correspondingly higher bit
|
||||||
Unlike certain parameters in the STK500, the JTAG ICE resets all its
|
clock period. Some programmers reset their bit clock value to the
|
||||||
parameters to default values when the programming software signs
|
default value when the programming software signs off, whilst others
|
||||||
off from the ICE, so for MCUs running at lower clock speeds, this
|
store the last used bit clock value. It is recommended to always
|
||||||
parameter must be specified on the command-line.
|
specify the bit clock if read/write speed is important.
|
||||||
You can use the 'default_bitclock' keyword in your
|
You can use the 'default_bitclock' keyword in your
|
||||||
|
.Pa ${HOME}/.config/avrdude/avrdude.rc
|
||||||
|
or
|
||||||
.Pa ${HOME}/.avrduderc
|
.Pa ${HOME}/.avrduderc
|
||||||
file to assign a default value to keep from having to specify this
|
file to assign a default value to keep from having to specify this
|
||||||
option on every invocation.
|
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
|
work with different programmers as long as the programmer supports the
|
||||||
Atmel AVR serial program method. You can use the 'default_programmer'
|
Atmel AVR serial program method. You can use the 'default_programmer'
|
||||||
keyword in your
|
keyword in your
|
||||||
|
.Pa ${HOME}/.config/avrdude/avrdude.rc
|
||||||
|
or
|
||||||
.Pa ${HOME}/.avrduderc
|
.Pa ${HOME}/.avrduderc
|
||||||
file to assign a default programmer to keep from having to specify
|
file to assign a default programmer to keep from having to specify
|
||||||
this option on every invocation.
|
this option on every invocation.
|
||||||
|
@ -507,6 +511,8 @@ actual connection to a target controller), this option can be used
|
||||||
together with
|
together with
|
||||||
.Fl t
|
.Fl t
|
||||||
to continue in terminal mode.
|
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
|
.It Fl i Ar delay
|
||||||
For bitbang-type programmers, delay for approximately
|
For bitbang-type programmers, delay for approximately
|
||||||
.Ar delay
|
.Ar delay
|
||||||
|
@ -1320,10 +1326,10 @@ the CS line being managed outside the application.
|
||||||
.Sh FILES
|
.Sh FILES
|
||||||
.Bl -tag -offset indent -width /dev/ppi0XXX
|
.Bl -tag -offset indent -width /dev/ppi0XXX
|
||||||
.It Pa /dev/ppi0
|
.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
|
hardware
|
||||||
.It Pa avrdude.conf
|
.It Pa avrdude.conf
|
||||||
programmer and parts configuration file
|
Programmer and parts configuration file
|
||||||
.Pp
|
.Pp
|
||||||
On Windows systems, this file is looked up in the same directory as the
|
On Windows systems, this file is looked up in the same directory as the
|
||||||
executable file.
|
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
|
relative to the path of the executable, then in the same directory as
|
||||||
the executable itself, and finally in the system default location
|
the executable itself, and finally in the system default location
|
||||||
.Pa ${PREFIX}/etc/avrdude.conf .
|
.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
|
.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
|
.It Pa ~/.inputrc
|
||||||
Initialization file for the
|
Initialization file for the
|
||||||
.Xr readline 3
|
.Xr readline 3
|
||||||
library
|
library
|
||||||
.It Pa ${PREFIX}/share/doc/avrdude/avrdude.pdf
|
.It Pa <prefix>/doc/avrdude/avrdude.pdf
|
||||||
Schematic of programming hardware
|
User manual
|
||||||
.El
|
.El
|
||||||
.\" .Sh EXAMPLES
|
.\" .Sh EXAMPLES
|
||||||
.Sh DIAGNOSTICS
|
.Sh DIAGNOSTICS
|
||||||
|
|
|
@ -389,7 +389,7 @@
|
||||||
# ATmega169 0x78
|
# ATmega169 0x78
|
||||||
|
|
||||||
#
|
#
|
||||||
# Overall avrdude defaults; suitable for ~/.avrduderc
|
# Overall avrdude defaults; suitable for ~/.config/avrdude/config
|
||||||
#
|
#
|
||||||
default_parallel = "@DEFAULT_PAR_PORT@";
|
default_parallel = "@DEFAULT_PAR_PORT@";
|
||||||
default_serial = "@DEFAULT_SER_PORT@";
|
default_serial = "@DEFAULT_SER_PORT@";
|
||||||
|
@ -1270,7 +1270,7 @@ programmer
|
||||||
id = "stk600";
|
id = "stk600";
|
||||||
desc = "Atmel STK600";
|
desc = "Atmel STK600";
|
||||||
type = "stk600";
|
type = "stk600";
|
||||||
prog_modes = PM_TPI | PM_ISP;
|
prog_modes = PM_TPI | PM_ISP | PM_PDI;
|
||||||
connection_type = usb;
|
connection_type = usb;
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -2294,7 +2294,7 @@ programmer
|
||||||
type = "jtagice3_updi";
|
type = "jtagice3_updi";
|
||||||
prog_modes = PM_UPDI;
|
prog_modes = PM_UPDI;
|
||||||
connection_type = usb;
|
connection_type = usb;
|
||||||
usbpid = 0x217f, 0x2180, 0x2181;
|
usbpid = 0x2180, 0x217f, 0x2181;
|
||||||
hvupdi_support = 1;
|
hvupdi_support = 1;
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -2308,7 +2308,7 @@ programmer
|
||||||
type = "jtagice3_pdi";
|
type = "jtagice3_pdi";
|
||||||
prog_modes = PM_PDI;
|
prog_modes = PM_PDI;
|
||||||
connection_type = usb;
|
connection_type = usb;
|
||||||
usbpid = 0x217f, 0x2180, 0x2181;
|
usbpid = 0x2180, 0x217f, 0x2181;
|
||||||
;
|
;
|
||||||
|
|
||||||
#------------------------------------------------------------
|
#------------------------------------------------------------
|
||||||
|
@ -2321,7 +2321,7 @@ programmer
|
||||||
type = "jtagice3_isp";
|
type = "jtagice3_isp";
|
||||||
prog_modes = PM_ISP;
|
prog_modes = PM_ISP;
|
||||||
connection_type = usb;
|
connection_type = usb;
|
||||||
usbpid = 0x217f, 0x2180, 0x2181;
|
usbpid = 0x2180, 0x217f, 0x2181;
|
||||||
;
|
;
|
||||||
|
|
||||||
#------------------------------------------------------------
|
#------------------------------------------------------------
|
||||||
|
|
|
@ -21,11 +21,14 @@
|
||||||
#ifndef avrdude_h
|
#ifndef avrdude_h
|
||||||
#define avrdude_h
|
#define avrdude_h
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#define SYSTEM_CONF_FILE "avrdude.conf"
|
#define SYSTEM_CONF_FILE "avrdude.conf"
|
||||||
#if defined(WIN32)
|
#if defined(WIN32)
|
||||||
#define USER_CONF_FILE "avrdude.rc"
|
#define USER_CONF_FILE "avrdude.rc"
|
||||||
#else
|
#else
|
||||||
#define USER_CONF_FILE ".avrduderc"
|
#define USER_CONF_FILE ".avrduderc"
|
||||||
|
#define XDG_USER_CONF_FILE "avrdude/avrdude.rc"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern char *progname; // name of program, for messages
|
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)
|
extern int quell_progress; // quell progress report -q, reduce effective verbosity level (-qq, -qqq)
|
||||||
|
|
||||||
int avrdude_message(int msglvl, const char *format, ...);
|
int avrdude_message(int msglvl, const char *format, ...);
|
||||||
int avrdude_message2(const char *fname, int msgmode, int msglvl, const char *format, ...);
|
int avrdude_message2(FILE *fp, int lno, const char *file, const char *func, int msgmode, int msglvl, const char *format, ...);
|
||||||
|
|
||||||
#define MSG_EXT_ERROR (-3) // OS-type error, no -v option, can be suppressed with -qqqqq
|
#define MSG_EXT_ERROR (-3) // OS-type error, no -v option, can be suppressed with -qqqqq
|
||||||
#define MSG_ERROR (-2) // Avrdude error, no -v option, can be suppressed with -qqqq
|
#define MSG_ERROR (-2) // Avrdude error, no -v option, can be suppressed with -qqqq
|
||||||
|
@ -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 MSG_TRACE2 5 // Displayed with -vvvvv
|
||||||
|
|
||||||
#define MSG2_PROGNAME 1 // Start by printing progname
|
#define MSG2_PROGNAME 1 // Start by printing progname
|
||||||
#define MSG2_FUNCTION 2 // Print calling function (1st arg) after progname
|
#define MSG2_FUNCTION 2 // Print calling function (1st arg) after progname if >= notice
|
||||||
#define MSG2_TYPE 4 // Print message type after function or progname
|
#define MSG2_FILELINE 4 // Print source file and line number after function if >= debug
|
||||||
#define MSG2_INDENT1 8 // Start by printing indentation of progname+1 blanks
|
#define MSG2_TYPE 8 // Print message type after function or progname
|
||||||
#define MSG2_INDENT2 16 // Start by printing indentation of progname+2 blanks
|
#define MSG2_INDENT1 16 // Start by printing indentation of progname+1 blanks
|
||||||
#define MSG2_FLUSH 32 // Flush before and after printing
|
#define MSG2_INDENT2 32 // Start by printing indentation of progname+2 blanks
|
||||||
|
#define MSG2_FLUSH 64 // Flush before and after printing
|
||||||
|
|
||||||
// Shortcuts
|
// Shortcuts
|
||||||
#define msg_ext_error(...) avrdude_message2(__func__, 0, MSG_EXT_ERROR, __VA_ARGS__)
|
#define msg_ext_error(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, 0, MSG_EXT_ERROR, __VA_ARGS__)
|
||||||
#define msg_error(...) avrdude_message2(__func__, 0, MSG_ERROR, __VA_ARGS__)
|
#define msg_error(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, 0, MSG_ERROR, __VA_ARGS__)
|
||||||
#define msg_warning(...) avrdude_message2(__func__, 0, MSG_WARNING, __VA_ARGS__)
|
#define msg_warning(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, 0, MSG_WARNING, __VA_ARGS__)
|
||||||
#define msg_info(...) avrdude_message2(__func__, 0, MSG_INFO, __VA_ARGS__)
|
#define msg_info(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, 0, MSG_INFO, __VA_ARGS__)
|
||||||
#define msg_notice(...) avrdude_message2(__func__, 0, MSG_NOTICE, __VA_ARGS__)
|
#define msg_notice(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, 0, MSG_NOTICE, __VA_ARGS__)
|
||||||
#define msg_notice2(...) avrdude_message2(__func__, 0, MSG_NOTICE2, __VA_ARGS__)
|
#define msg_notice2(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, 0, MSG_NOTICE2, __VA_ARGS__)
|
||||||
#define msg_debug(...) avrdude_message2(__func__, 0, MSG_DEBUG, __VA_ARGS__)
|
#define msg_debug(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, 0, MSG_DEBUG, __VA_ARGS__)
|
||||||
#define msg_trace(...) avrdude_message2(__func__, 0, MSG_TRACE, __VA_ARGS__)
|
#define msg_trace(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, 0, MSG_TRACE, __VA_ARGS__)
|
||||||
#define msg_trace2(...) avrdude_message2(__func__, 0, MSG_TRACE2, __VA_ARGS__)
|
#define msg_trace2(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, 0, MSG_TRACE2, __VA_ARGS__)
|
||||||
|
|
||||||
#define pmsg_ext_error(...) avrdude_message2(__func__, MSG2_PROGNAME|MSG2_FUNCTION|MSG2_TYPE|MSG2_FLUSH, MSG_EXT_ERROR, __VA_ARGS__)
|
#define pmsg_ext_error(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FUNCTION|MSG2_FILELINE|MSG2_TYPE|MSG2_FLUSH, MSG_EXT_ERROR, __VA_ARGS__)
|
||||||
#define pmsg_error(...) avrdude_message2(__func__, MSG2_PROGNAME|MSG2_FUNCTION|MSG2_TYPE|MSG2_FLUSH, MSG_ERROR, __VA_ARGS__)
|
#define pmsg_error(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FUNCTION|MSG2_FILELINE|MSG2_TYPE|MSG2_FLUSH, MSG_ERROR, __VA_ARGS__)
|
||||||
#define pmsg_warning(...) avrdude_message2(__func__, MSG2_PROGNAME|MSG2_FUNCTION|MSG2_TYPE|MSG2_FLUSH, MSG_WARNING, __VA_ARGS__)
|
#define pmsg_warning(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FUNCTION|MSG2_FILELINE|MSG2_TYPE|MSG2_FLUSH, MSG_WARNING, __VA_ARGS__)
|
||||||
#define pmsg_info(...) avrdude_message2(__func__, MSG2_PROGNAME|MSG2_FLUSH, MSG_INFO, __VA_ARGS__)
|
#define pmsg_info(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FLUSH, MSG_INFO, __VA_ARGS__)
|
||||||
#define pmsg_notice(...) avrdude_message2(__func__, MSG2_PROGNAME|MSG2_FLUSH, MSG_NOTICE, __VA_ARGS__)
|
#define pmsg_notice(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FLUSH, MSG_NOTICE, __VA_ARGS__)
|
||||||
#define pmsg_notice2(...) avrdude_message2(__func__, MSG2_PROGNAME|MSG2_FLUSH, MSG_NOTICE2, __VA_ARGS__)
|
#define pmsg_notice2(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FLUSH, MSG_NOTICE2, __VA_ARGS__)
|
||||||
#define pmsg_debug(...) avrdude_message2(__func__, MSG2_PROGNAME|MSG2_FLUSH, MSG_DEBUG, __VA_ARGS__)
|
#define pmsg_debug(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FLUSH, MSG_DEBUG, __VA_ARGS__)
|
||||||
#define pmsg_trace(...) avrdude_message2(__func__, MSG2_PROGNAME|MSG2_FLUSH, MSG_TRACE, __VA_ARGS__)
|
#define pmsg_trace(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FLUSH, MSG_TRACE, __VA_ARGS__)
|
||||||
#define pmsg_trace2(...) avrdude_message2(__func__, MSG2_PROGNAME|MSG2_FLUSH, MSG_TRACE2, __VA_ARGS__)
|
#define pmsg_trace2(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FLUSH, MSG_TRACE2, __VA_ARGS__)
|
||||||
|
|
||||||
#define imsg_ext_error(...) avrdude_message2(__func__, MSG2_INDENT1|MSG2_FLUSH, MSG_EXT_ERROR, __VA_ARGS__)
|
#define imsg_ext_error(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT1|MSG2_FLUSH, MSG_EXT_ERROR, __VA_ARGS__)
|
||||||
#define imsg_error(...) avrdude_message2(__func__, MSG2_INDENT1|MSG2_FLUSH, MSG_ERROR, __VA_ARGS__)
|
#define imsg_error(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT1|MSG2_FLUSH, MSG_ERROR, __VA_ARGS__)
|
||||||
#define imsg_warning(...) avrdude_message2(__func__, MSG2_INDENT1|MSG2_FLUSH, MSG_WARNING, __VA_ARGS__)
|
#define imsg_warning(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT1|MSG2_FLUSH, MSG_WARNING, __VA_ARGS__)
|
||||||
#define imsg_info(...) avrdude_message2(__func__, MSG2_INDENT2|MSG2_FLUSH, MSG_INFO, __VA_ARGS__)
|
#define imsg_info(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT2|MSG2_FLUSH, MSG_INFO, __VA_ARGS__)
|
||||||
#define imsg_notice(...) avrdude_message2(__func__, MSG2_INDENT2|MSG2_FLUSH, MSG_NOTICE, __VA_ARGS__)
|
#define imsg_notice(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT2|MSG2_FLUSH, MSG_NOTICE, __VA_ARGS__)
|
||||||
#define imsg_notice2(...) avrdude_message2(__func__, MSG2_INDENT2|MSG2_FLUSH, MSG_NOTICE2, __VA_ARGS__)
|
#define imsg_notice2(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT2|MSG2_FLUSH, MSG_NOTICE2, __VA_ARGS__)
|
||||||
#define imsg_debug(...) avrdude_message2(__func__, MSG2_INDENT2|MSG2_FLUSH, MSG_DEBUG, __VA_ARGS__)
|
#define imsg_debug(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT2|MSG2_FLUSH, MSG_DEBUG, __VA_ARGS__)
|
||||||
#define imsg_trace(...) avrdude_message2(__func__, MSG2_INDENT2|MSG2_FLUSH, MSG_TRACE, __VA_ARGS__)
|
#define imsg_trace(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT2|MSG2_FLUSH, MSG_TRACE, __VA_ARGS__)
|
||||||
#define imsg_trace2(...) avrdude_message2(__func__, MSG2_INDENT2|MSG2_FLUSH, MSG_TRACE2, __VA_ARGS__)
|
#define imsg_trace2(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT2|MSG2_FLUSH, MSG_TRACE2, __VA_ARGS__)
|
||||||
|
|
||||||
|
#define term_out(...) avrdude_message2(stdout, __LINE__, __FILE__, __func__, MSG2_FLUSH, MSG_INFO, __VA_ARGS__)
|
||||||
|
#define fmsg_out(fp, ...) avrdude_message2(fp, __LINE__, __FILE__, __func__, MSG2_FLUSH, MSG_INFO, __VA_ARGS__)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -498,22 +498,15 @@ void avr_mem_display(const char *prefix, FILE *f, const AVRMEM *m,
|
||||||
int i, j;
|
int i, j;
|
||||||
char * optr;
|
char * optr;
|
||||||
|
|
||||||
if (m == NULL) {
|
if (m == NULL || verbose > 2) {
|
||||||
fprintf(f,
|
fprintf(f,
|
||||||
"%s Block Poll Page Polled\n"
|
"%s Block Poll Page Polled\n"
|
||||||
"%sMemory Type Alias Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack\n"
|
"%sMemory Type Alias Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack\n"
|
||||||
"%s----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------\n",
|
"%s----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------\n",
|
||||||
prefix, prefix, prefix);
|
prefix, prefix, prefix);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
if (verbose > 2) {
|
|
||||||
fprintf(f,
|
|
||||||
"%s Block Poll Page Polled\n"
|
|
||||||
"%sMemory Type Alias Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack\n"
|
|
||||||
"%s----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------\n",
|
|
||||||
prefix, prefix, prefix);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (m != NULL) {
|
||||||
// Only print memory section if the previous section printed isn't identical
|
// Only print memory section if the previous section printed isn't identical
|
||||||
if(prev_mem_offset != m->offset || prev_mem_size != m->size || (strcmp(p->family_id, "") == 0)) {
|
if(prev_mem_offset != m->offset || prev_mem_size != m->size || (strcmp(p->family_id, "") == 0)) {
|
||||||
prev_mem_offset = m->offset;
|
prev_mem_offset = m->offset;
|
||||||
|
|
|
@ -440,19 +440,21 @@ Override the RS-232 connection baud rate specified in the respective
|
||||||
programmer's entry of the configuration file.
|
programmer's entry of the configuration file.
|
||||||
|
|
||||||
@item -B @var{bitclock}
|
@item -B @var{bitclock}
|
||||||
Specify the bit clock period for the JTAG interface or the ISP clock (JTAG ICE only).
|
Specify the bit clock period for the JTAG, PDI, TPI, UPDI, or ISP
|
||||||
The value is a floating-point number in microseconds.
|
interface. The value is a floating-point number in microseconds.
|
||||||
Alternatively, the value might be suffixed with "Hz", "kHz", or "MHz",
|
Alternatively, the value might be suffixed with "Hz", "kHz" or
|
||||||
in order to specify the bit clock frequency, rather than a period.
|
"MHz" in order to specify the bit clock frequency rather than a
|
||||||
The default value of the JTAG ICE results in about 1 microsecond bit
|
period. Some programmers default their bit clock value to a 1
|
||||||
clock period, suitable for target MCUs running at 4 MHz clock and
|
microsecond bit clock period, suitable for target MCUs running at 4
|
||||||
above.
|
MHz clock and above. Slower MCUs need a correspondingly higher bit
|
||||||
Unlike certain parameters in the STK500, the JTAG ICE resets all its
|
clock period. Some programmers reset their bit clock value to the
|
||||||
parameters to default values when the programming software signs
|
default value when the programming software signs off, whilst
|
||||||
off from the ICE, so for MCUs running at lower clock speeds, this
|
others store the last used bit clock value. It is recommended to
|
||||||
parameter must be specified on the command-line.
|
always specify the bit clock if read/write speed is important. You
|
||||||
It can also be set in the configuration file by using the 'default_bitclock'
|
can use the 'default_bitclock' keyword in your
|
||||||
keyword.
|
@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}
|
@item -c @var{programmer-id}
|
||||||
Specify the programmer to be used. AVRDUDE knows about several common
|
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
|
adjust parameters local to the programming tool (independent of an
|
||||||
actual connection to a target controller), this option can be used
|
actual connection to a target controller), this option can be used
|
||||||
together with @option{-t} to continue in terminal mode.
|
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}
|
@item -i @var{delay}
|
||||||
For bitbang-type programmers, delay for approximately
|
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
|
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
|
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
|
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
|
of AVRDUDE. Likewise, if you have a parallel port programmer that is
|
||||||
not supported by AVRDUDE, chances are good that you can copy and
|
not supported, chances are that you can copy an
|
||||||
existing programmer definition, and with only a few changes, make your
|
existing programmer definition and, with only a few changes, make your
|
||||||
programmer work with AVRDUDE.
|
programmer work.
|
||||||
|
|
||||||
AVRDUDE first looks for a system wide configuration file in a platform
|
AVRDUDE first looks for a system wide configuration file in a platform
|
||||||
dependent location. On Unix, this is usually
|
dependent location. On Unix, this is usually
|
||||||
@code{/usr/local/etc/avrdude.conf}, while on Windows it is usually in the
|
@code{/usr/local/etc/avrdude.conf}, whilst on Windows it is usually in the
|
||||||
same location as the executable file. The name of this file can be
|
same location as the executable file. The full name of this file can be
|
||||||
changed using the @option{-C} command line option. After the system wide
|
specified using the @option{-C} command line option. After parsing the system wide
|
||||||
configuration file is parsed, AVRDUDE looks for a per-user configuration
|
configuration file, AVRDUDE looks for a per-user configuration
|
||||||
file to augment or override the system wide defaults. On Unix, the
|
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
|
per-user file is @code{$@{XDG_CONFIG_HOME@}/avrdude/avrdude.rc}, whereas
|
||||||
Windows, this file is the @code{avrdude.rc} file located in the same
|
if @code{$@{XDG_CONFIG_HOME@}} is either not set or empty,
|
||||||
directory as the executable.
|
@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
|
@menu
|
||||||
* AVRDUDE Defaults::
|
* AVRDUDE Defaults::
|
||||||
|
@ -3044,14 +3051,15 @@ See also: @url{http://www.libusb.org/ticket/6}
|
||||||
@item
|
@item
|
||||||
Problem: after flashing a firmware that reduces the target's clock
|
Problem: after flashing a firmware that reduces the target's clock
|
||||||
speed (e.g. through the @code{CLKPR} register), further ISP connection
|
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
|
Solution: Even though ISP starts with pulling @var{/RESET} low, the
|
||||||
target continues to run at the internal clock speed as defined by the
|
target continues to run at the internal clock speed either as defined by
|
||||||
firmware running before. Therefore, the ISP clock speed must be
|
the firmware running before or as set by the factory. Therefore, the
|
||||||
reduced appropriately (to less than 1/4 of the internal clock speed)
|
ISP clock speed must be reduced appropriately (to less than 1/4 of the
|
||||||
using the -B option before the ISP initialization sequence will
|
internal clock speed) using the -B option before the ISP initialization
|
||||||
succeed.
|
sequence will succeed.
|
||||||
|
|
||||||
As that slows down the entire subsequent ISP session, it might make
|
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
|
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
|
FLIP2_MEM_UNIT_EXT_MEM_DF = 0x10
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBUSB
|
||||||
|
|
||||||
/* EXPORTED PROGRAMMER FUNCTION PROTOTYPES */
|
/* EXPORTED PROGRAMMER FUNCTION PROTOTYPES */
|
||||||
|
|
||||||
static int flip2_open(PROGRAMMER *pgm, const char *port_spec);
|
static int flip2_open(PROGRAMMER *pgm, const char *port_spec);
|
||||||
|
@ -146,8 +148,6 @@ static void flip2_setup(PROGRAMMER * pgm);
|
||||||
static void flip2_teardown(PROGRAMMER * pgm);
|
static void flip2_teardown(PROGRAMMER * pgm);
|
||||||
|
|
||||||
/* INTERNAL PROGRAMMER FUNCTION PROTOTYPES */
|
/* INTERNAL PROGRAMMER FUNCTION PROTOTYPES */
|
||||||
#ifdef HAVE_LIBUSB
|
|
||||||
// The internal ones are made conditional, as they're not defined further down #ifndef HAVE_LIBUSB
|
|
||||||
|
|
||||||
static void flip2_show_info(struct flip2 *flip2);
|
static void flip2_show_info(struct flip2 *flip2);
|
||||||
|
|
||||||
|
|
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,
|
static int jtag3_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
|
||||||
unsigned long addr, unsigned char data);
|
unsigned long addr, unsigned char data);
|
||||||
static int jtag3_set_sck_period(const PROGRAMMER *pgm, double v);
|
static int jtag3_set_sck_period(const PROGRAMMER *pgm, double v);
|
||||||
void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p);
|
void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp);
|
||||||
static int jtag3_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
|
static int jtag3_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
|
||||||
unsigned int page_size,
|
unsigned int page_size,
|
||||||
unsigned int addr, unsigned int n_bytes);
|
unsigned int addr, unsigned int n_bytes);
|
||||||
|
@ -1077,7 +1077,7 @@ static int jtag3_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
if (PDATA(pgm)->set_sck(pgm, parm) < 0)
|
if (PDATA(pgm)->set_sck(pgm, parm) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
jtag3_print_parms1(pgm, progbuf);
|
jtag3_print_parms1(pgm, progbuf, stderr);
|
||||||
if (conn == PARM3_CONN_JTAG)
|
if (conn == PARM3_CONN_JTAG)
|
||||||
{
|
{
|
||||||
pmsg_notice2("jtag3_initialize(): "
|
pmsg_notice2("jtag3_initialize(): "
|
||||||
|
@ -1504,6 +1504,30 @@ int jtag3_open_common(PROGRAMMER *pgm, const char *port) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (rv < 0) {
|
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: ",
|
pmsg_error("did not find any device matching VID 0x%04x and PID list: ",
|
||||||
(unsigned) pinfo.usbinfo.vid);
|
(unsigned) pinfo.usbinfo.vid);
|
||||||
int notfirst = 0;
|
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];
|
unsigned char buf[3];
|
||||||
|
|
||||||
if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_VTARGET, buf, 2) < 0)
|
if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_VTARGET, buf, 2) < 0)
|
||||||
return;
|
return;
|
||||||
msg_info("%sVtarget %s: %.2f V\n", p,
|
fmsg_out(fp, "%sVtarget %s: %.2f V\n", p,
|
||||||
verbose? "": " ", b2_to_u16(buf)/1000.0);
|
verbose? "": " ", b2_to_u16(buf)/1000.0);
|
||||||
|
|
||||||
// Print features unique to the Power Debugger
|
// Print features unique to the Power Debugger
|
||||||
|
@ -2350,7 +2374,7 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p) {
|
||||||
if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_VADJUST, buf, 2) < 0)
|
if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_VADJUST, buf, 2) < 0)
|
||||||
return;
|
return;
|
||||||
analog_raw_data = b2_to_u16(buf);
|
analog_raw_data = b2_to_u16(buf);
|
||||||
msg_info("%sVout set %s: %.2f V\n", p,
|
fmsg_out(fp, "%sVout set %s: %.2f V\n", p,
|
||||||
verbose? "": " ", analog_raw_data / 1000.0);
|
verbose? "": " ", analog_raw_data / 1000.0);
|
||||||
|
|
||||||
// Read measured generator voltage value (VOUT)
|
// Read measured generator voltage value (VOUT)
|
||||||
|
@ -2362,7 +2386,7 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p) {
|
||||||
else {
|
else {
|
||||||
if (analog_raw_data & 0x0800)
|
if (analog_raw_data & 0x0800)
|
||||||
analog_raw_data |= 0xF000;
|
analog_raw_data |= 0xF000;
|
||||||
msg_info("%sVout measured %s: %.02f V\n", p,
|
fmsg_out(fp, "%sVout measured %s: %.02f V\n", p,
|
||||||
verbose? "": " ", ((float) analog_raw_data / -200.0));
|
verbose? "": " ", ((float) analog_raw_data / -200.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2375,7 +2399,7 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p) {
|
||||||
else {
|
else {
|
||||||
if (analog_raw_data & 0x0800)
|
if (analog_raw_data & 0x0800)
|
||||||
analog_raw_data |= 0xF000;
|
analog_raw_data |= 0xF000;
|
||||||
msg_info("%sCh A voltage %s: %.03f V\n", p,
|
fmsg_out(fp, "%sCh A voltage %s: %.03f V\n", p,
|
||||||
verbose? "": " ", ((float) analog_raw_data / -200.0));
|
verbose? "": " ", ((float) analog_raw_data / -200.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2386,7 +2410,7 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p) {
|
||||||
if (buf[0] != 0x90)
|
if (buf[0] != 0x90)
|
||||||
pmsg_error("invalid PARM3_ANALOG_A_CURRENT data packet format\n");
|
pmsg_error("invalid PARM3_ANALOG_A_CURRENT data packet format\n");
|
||||||
else
|
else
|
||||||
msg_info("%sCh A current %s: %.3f mA\n", p,
|
fmsg_out(fp, "%sCh A current %s: %.3f mA\n", p,
|
||||||
verbose? "": " ", (float) analog_raw_data * 0.003472);
|
verbose? "": " ", (float) analog_raw_data * 0.003472);
|
||||||
|
|
||||||
// Read channel B voltage
|
// Read channel B voltage
|
||||||
|
@ -2398,7 +2422,7 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p) {
|
||||||
else {
|
else {
|
||||||
if (analog_raw_data & 0x0800)
|
if (analog_raw_data & 0x0800)
|
||||||
analog_raw_data |= 0xF000;
|
analog_raw_data |= 0xF000;
|
||||||
msg_info("%sCh B voltage %s: %.03f V\n", p,
|
fmsg_out(fp, "%sCh B voltage %s: %.03f V\n", p,
|
||||||
verbose? "": " ", (float) analog_raw_data / -200.0);
|
verbose? "": " ", (float) analog_raw_data / -200.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2411,7 +2435,7 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p) {
|
||||||
else {
|
else {
|
||||||
if (analog_raw_data & 0x0800)
|
if (analog_raw_data & 0x0800)
|
||||||
analog_raw_data |= 0xF000;
|
analog_raw_data |= 0xF000;
|
||||||
msg_info("%sCh B current %s: %.3f mA\n", p,
|
fmsg_out(fp, "%sCh B current %s: %.3f mA\n", p,
|
||||||
verbose? "": " ", (float) analog_raw_data * 0.555556);
|
verbose? "": " ", (float) analog_raw_data * 0.555556);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -2422,33 +2446,33 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p) {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (b2_to_u16(buf) > 0) {
|
if (b2_to_u16(buf) > 0) {
|
||||||
msg_info("%sJTAG clock megaAVR/program : %u kHz\n", p, b2_to_u16(buf));
|
fmsg_out(fp, "%sJTAG clock megaAVR/program : %u kHz\n", p, b2_to_u16(buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_MEGA_DEBUG, buf, 2) < 0)
|
if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_MEGA_DEBUG, buf, 2) < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (b2_to_u16(buf) > 0) {
|
if (b2_to_u16(buf) > 0) {
|
||||||
msg_info("%sJTAG clock megaAVR/debug : %u kHz\n", p, b2_to_u16(buf));
|
fmsg_out(fp, "%sJTAG clock megaAVR/debug : %u kHz\n", p, b2_to_u16(buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_XMEGA_JTAG, buf, 2) < 0)
|
if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_XMEGA_JTAG, buf, 2) < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (b2_to_u16(buf) > 0) {
|
if (b2_to_u16(buf) > 0) {
|
||||||
msg_info("%sJTAG clock Xmega : %u kHz\n", p, b2_to_u16(buf));
|
fmsg_out(fp, "%sJTAG clock Xmega : %u kHz\n", p, b2_to_u16(buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_XMEGA_PDI, buf, 2) < 0)
|
if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_XMEGA_PDI, buf, 2) < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (b2_to_u16(buf) > 0) {
|
if (b2_to_u16(buf) > 0) {
|
||||||
msg_info("%sPDI/UPDI clock Xmega/megaAVR : %u kHz\n", p, b2_to_u16(buf));
|
fmsg_out(fp, "%sPDI/UPDI clock Xmega/megaAVR : %u kHz\n", p, b2_to_u16(buf));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void jtag3_print_parms(const PROGRAMMER *pgm) {
|
static void jtag3_print_parms(const PROGRAMMER *pgm, FILE *fp) {
|
||||||
jtag3_print_parms1(pgm, "");
|
jtag3_print_parms1(pgm, "", fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned char jtag3_memtype(const PROGRAMMER *pgm, const AVRPART *p, unsigned long addr) {
|
static unsigned char jtag3_memtype(const PROGRAMMER *pgm, const AVRPART *p, unsigned long addr) {
|
||||||
|
|
|
@ -38,7 +38,7 @@ int jtag3_setparm(const PROGRAMMER *pgm, unsigned char scope,
|
||||||
unsigned char *value, unsigned char length);
|
unsigned char *value, unsigned char length);
|
||||||
int jtag3_command(const PROGRAMMER *pgm, unsigned char *cmd, unsigned int cmdlen,
|
int jtag3_command(const PROGRAMMER *pgm, unsigned char *cmd, unsigned int cmdlen,
|
||||||
unsigned char **resp, const char *descr);
|
unsigned char **resp, const char *descr);
|
||||||
void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p);
|
void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp);
|
||||||
int jtag3_set_vtarget(const PROGRAMMER *pgm, double voltage);
|
int jtag3_set_vtarget(const PROGRAMMER *pgm, double voltage);
|
||||||
extern const char jtag3_desc[];
|
extern const char jtag3_desc[];
|
||||||
extern const char jtag3_dw_desc[];
|
extern const char jtag3_dw_desc[];
|
||||||
|
|
|
@ -104,7 +104,7 @@ static int jtagmkI_getparm(const PROGRAMMER *pgm, unsigned char parm,
|
||||||
unsigned char * value);
|
unsigned char * value);
|
||||||
static int jtagmkI_setparm(const PROGRAMMER *pgm, unsigned char parm,
|
static int jtagmkI_setparm(const PROGRAMMER *pgm, unsigned char parm,
|
||||||
unsigned char value);
|
unsigned char value);
|
||||||
static void jtagmkI_print_parms1(const PROGRAMMER *pgm, const char *p);
|
static void jtagmkI_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp);
|
||||||
|
|
||||||
static int jtagmkI_resync(const PROGRAMMER *pgm, int maxtries, int signon);
|
static int jtagmkI_resync(const PROGRAMMER *pgm, int maxtries, int signon);
|
||||||
|
|
||||||
|
@ -1170,13 +1170,13 @@ static void jtagmkI_display(const PROGRAMMER *pgm, const char *p) {
|
||||||
msg_info("%sICE HW version: 0x%02x\n", p, hw);
|
msg_info("%sICE HW version: 0x%02x\n", p, hw);
|
||||||
msg_info("%sICE FW version: 0x%02x\n", p, fw);
|
msg_info("%sICE FW version: 0x%02x\n", p, fw);
|
||||||
|
|
||||||
jtagmkI_print_parms1(pgm, p);
|
jtagmkI_print_parms1(pgm, p, stderr);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void jtagmkI_print_parms1(const PROGRAMMER *pgm, const char *p) {
|
static void jtagmkI_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp) {
|
||||||
unsigned char vtarget, jtag_clock;
|
unsigned char vtarget, jtag_clock;
|
||||||
const char *clkstr;
|
const char *clkstr;
|
||||||
double clk;
|
double clk;
|
||||||
|
@ -1211,15 +1211,15 @@ static void jtagmkI_print_parms1(const PROGRAMMER *pgm, const char *p) {
|
||||||
clk = 1e6;
|
clk = 1e6;
|
||||||
}
|
}
|
||||||
|
|
||||||
msg_info("%sVtarget : %.1f V\n", p, 6.25 * (unsigned)vtarget / 255.0);
|
fmsg_out(fp, "%sVtarget : %.1f V\n", p, 6.25 * (unsigned)vtarget / 255.0);
|
||||||
msg_info("%sJTAG clock : %s (%.1f us)\n", p, clkstr, 1.0e6 / clk);
|
fmsg_out(fp, "%sJTAG clock : %s (%.1f us)\n", p, clkstr, 1.0e6 / clk);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void jtagmkI_print_parms(const PROGRAMMER *pgm) {
|
static void jtagmkI_print_parms(const PROGRAMMER *pgm, FILE *fp) {
|
||||||
jtagmkI_print_parms1(pgm, "");
|
jtagmkI_print_parms1(pgm, "", fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char jtagmkI_desc[] = "Atmel JTAG ICE mkI";
|
const char jtagmkI_desc[] = "Atmel JTAG ICE mkI";
|
||||||
|
|
|
@ -144,7 +144,7 @@ static int jtagmkII_reset(const PROGRAMMER *pgm, unsigned char flags);
|
||||||
static int jtagmkII_set_sck_period(const PROGRAMMER *pgm, double v);
|
static int jtagmkII_set_sck_period(const PROGRAMMER *pgm, double v);
|
||||||
static int jtagmkII_setparm(const PROGRAMMER *pgm, unsigned char parm,
|
static int jtagmkII_setparm(const PROGRAMMER *pgm, unsigned char parm,
|
||||||
unsigned char * value);
|
unsigned char * value);
|
||||||
static void jtagmkII_print_parms1(const PROGRAMMER *pgm, const char *p);
|
static void jtagmkII_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp);
|
||||||
static int jtagmkII_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
|
static int jtagmkII_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
|
||||||
unsigned int page_size,
|
unsigned int page_size,
|
||||||
unsigned int addr, unsigned int n_bytes);
|
unsigned int addr, unsigned int n_bytes);
|
||||||
|
@ -2508,13 +2508,13 @@ static void jtagmkII_display(const PROGRAMMER *pgm, const char *p) {
|
||||||
PDATA(pgm)->serno[0], PDATA(pgm)->serno[1], PDATA(pgm)->serno[2],
|
PDATA(pgm)->serno[0], PDATA(pgm)->serno[1], PDATA(pgm)->serno[2],
|
||||||
PDATA(pgm)->serno[3], PDATA(pgm)->serno[4], PDATA(pgm)->serno[5]);
|
PDATA(pgm)->serno[3], PDATA(pgm)->serno[4], PDATA(pgm)->serno[5]);
|
||||||
|
|
||||||
jtagmkII_print_parms1(pgm, p);
|
jtagmkII_print_parms1(pgm, p, stderr);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void jtagmkII_print_parms1(const PROGRAMMER *pgm, const char *p) {
|
static void jtagmkII_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp) {
|
||||||
unsigned char vtarget[4], jtag_clock[4];
|
unsigned char vtarget[4], jtag_clock[4];
|
||||||
char clkbuf[20];
|
char clkbuf[20];
|
||||||
double clk;
|
double clk;
|
||||||
|
@ -2522,7 +2522,7 @@ static void jtagmkII_print_parms1(const PROGRAMMER *pgm, const char *p) {
|
||||||
if (jtagmkII_getparm(pgm, PAR_OCD_VTARGET, vtarget) < 0)
|
if (jtagmkII_getparm(pgm, PAR_OCD_VTARGET, vtarget) < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
msg_info("%sVtarget : %.1f V\n", p, b2_to_u16(vtarget) / 1000.0);
|
fmsg_out(fp, "%sVtarget : %.1f V\n", p, b2_to_u16(vtarget) / 1000.0);
|
||||||
|
|
||||||
if ((pgm->flag & PGM_FL_IS_JTAG)) {
|
if ((pgm->flag & PGM_FL_IS_JTAG)) {
|
||||||
if (jtagmkII_getparm(pgm, PAR_OCD_JTAG_CLK, jtag_clock) < 0)
|
if (jtagmkII_getparm(pgm, PAR_OCD_JTAG_CLK, jtag_clock) < 0)
|
||||||
|
@ -2541,15 +2541,15 @@ static void jtagmkII_print_parms1(const PROGRAMMER *pgm, const char *p) {
|
||||||
sprintf(clkbuf, "%.1f kHz", 5.35e3 / (double)jtag_clock[0]);
|
sprintf(clkbuf, "%.1f kHz", 5.35e3 / (double)jtag_clock[0]);
|
||||||
clk = 5.35e6 / (double)jtag_clock[0];
|
clk = 5.35e6 / (double)jtag_clock[0];
|
||||||
|
|
||||||
msg_info("%sJTAG clock : %s (%.1f us)\n", p, clkbuf, 1.0e6 / clk);
|
fmsg_out(fp, "%sJTAG clock : %s (%.1f us)\n", p, clkbuf, 1.0e6 / clk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void jtagmkII_print_parms(const PROGRAMMER *pgm) {
|
static void jtagmkII_print_parms(const PROGRAMMER *pgm, FILE *fp) {
|
||||||
jtagmkII_print_parms1(pgm, "");
|
jtagmkII_print_parms1(pgm, "", fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned char jtagmkII_memtype(const PROGRAMMER *pgm, const AVRPART *p, unsigned long addr) {
|
static unsigned char jtagmkII_memtype(const PROGRAMMER *pgm, const AVRPART *p, unsigned long addr) {
|
||||||
|
|
|
@ -783,7 +783,8 @@ typedef struct programmer_t {
|
||||||
unsigned long addr, unsigned char *value);
|
unsigned long addr, unsigned char *value);
|
||||||
int (*read_sig_bytes) (const struct programmer_t *pgm, const AVRPART *p, const AVRMEM *m);
|
int (*read_sig_bytes) (const struct programmer_t *pgm, const AVRPART *p, const AVRMEM *m);
|
||||||
int (*read_sib) (const struct programmer_t *pgm, const AVRPART *p, char *sib);
|
int (*read_sib) (const struct programmer_t *pgm, const AVRPART *p, char *sib);
|
||||||
void (*print_parms) (const struct programmer_t *pgm);
|
int (*term_keep_alive)(const struct programmer_t *pgm, const AVRPART *p);
|
||||||
|
void (*print_parms) (const struct programmer_t *pgm, FILE *fp);
|
||||||
int (*set_vtarget) (const struct programmer_t *pgm, double v);
|
int (*set_vtarget) (const struct programmer_t *pgm, double v);
|
||||||
int (*set_varef) (const struct programmer_t *pgm, unsigned int chan, double v);
|
int (*set_varef) (const struct programmer_t *pgm, unsigned int chan, double v);
|
||||||
int (*set_fosc) (const struct programmer_t *pgm, double v);
|
int (*set_fosc) (const struct programmer_t *pgm, double v);
|
||||||
|
|
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;
|
int rc = 0;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
|
if(msglvl <= MSG_ERROR) // Serious error? Freee progress bars (if any)
|
||||||
|
report_progress(1, -1, NULL);
|
||||||
|
|
||||||
if(msgmode & MSG2_FLUSH) {
|
if(msgmode & MSG2_FLUSH) {
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reduce effective verbosity level by number of -q above one
|
// Reduce effective verbosity level by number of -q above one when printing to stderr
|
||||||
if ((quell_progress < 2? verbose: verbose+1-quell_progress) >= msglvl) {
|
if ((quell_progress < 2 || fp != stderr? verbose: verbose+1-quell_progress) >= msglvl) {
|
||||||
if(msgmode & MSG2_PROGNAME) {
|
if(msgmode & MSG2_PROGNAME) {
|
||||||
fprintf(stderr, "%s", progname);
|
fprintf(fp, "%s", progname);
|
||||||
if(verbose >= MSG_NOTICE && (msgmode & MSG2_FUNCTION))
|
if(verbose >= MSG_NOTICE && (msgmode & MSG2_FUNCTION))
|
||||||
fprintf(stderr, " %s()", fname);
|
fprintf(fp, " %s()", func);
|
||||||
|
if(verbose >= MSG_DEBUG && (msgmode & MSG2_FILELINE)) {
|
||||||
|
const char *pr = strrchr(file, '/'); // only print basename
|
||||||
|
#if defined (WIN32)
|
||||||
|
if(!pr)
|
||||||
|
pr = strrchr(file, '\\');
|
||||||
|
#endif
|
||||||
|
pr = pr? pr+1: file;
|
||||||
|
fprintf(fp, " [%s:%d]", pr, lno);
|
||||||
|
}
|
||||||
if(msgmode & MSG2_TYPE)
|
if(msgmode & MSG2_TYPE)
|
||||||
fprintf(stderr, " %s", avrdude_message_type(msglvl));
|
fprintf(fp, " %s", avrdude_message_type(msglvl));
|
||||||
fprintf(stderr, ": ");
|
fprintf(fp, ": ");
|
||||||
} else if(msgmode & MSG2_INDENT1) {
|
} else if(msgmode & MSG2_INDENT1) {
|
||||||
fprintf(stderr, "%*s", (int) strlen(progname)+1, "");
|
fprintf(fp, "%*s", (int) strlen(progname)+1, "");
|
||||||
} else if(msgmode & MSG2_INDENT2) {
|
} else if(msgmode & MSG2_INDENT2) {
|
||||||
fprintf(stderr, "%*s", (int) strlen(progname)+2, "");
|
fprintf(fp, "%*s", (int) strlen(progname)+2, "");
|
||||||
}
|
}
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
rc = vfprintf(stderr, format, ap);
|
rc = vfprintf(fp, format, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(msgmode & MSG2_FLUSH)
|
if(msgmode & MSG2_FLUSH)
|
||||||
fflush(stderr);
|
fflush(fp);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -155,14 +167,14 @@ static void usage(void)
|
||||||
"Options:\n"
|
"Options:\n"
|
||||||
" -p <partno> Specify AVR device\n"
|
" -p <partno> Specify AVR device\n"
|
||||||
" -b <baudrate> Override RS-232 baud rate\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 <config-file> Specify location of configuration file\n"
|
||||||
" -c <programmer> Specify programmer type\n"
|
" -c <programmer> Specify programmer type\n"
|
||||||
" -A Disable trailing-0xff removal from file and AVR read\n"
|
" -A Disable trailing-0xff removal from file and AVR read\n"
|
||||||
" -D Disable auto erase for flash memory; implies -A\n"
|
" -D Disable auto erase for flash memory; implies -A\n"
|
||||||
" -i <delay> ISP Clock Delay [in microseconds]\n"
|
" -i <delay> ISP Clock Delay [in microseconds]\n"
|
||||||
" -P <port> Specify connection port\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"
|
" -e Perform a chip erase\n"
|
||||||
" -O Perform RC oscillator calibration (see AVR053)\n"
|
" -O Perform RC oscillator calibration (see AVR053)\n"
|
||||||
" -U <memtype>:r|w|v:<filename>[:format]\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
|
* main routine
|
||||||
*/
|
*/
|
||||||
|
@ -465,10 +503,6 @@ int main(int argc, char * argv [])
|
||||||
char * logfile; /* Use logfile rather than stderr for diagnostics */
|
char * logfile; /* Use logfile rather than stderr for diagnostics */
|
||||||
enum updateflags uflags = UF_AUTO_ERASE | UF_VERIFY; /* Flags for do_op() */
|
enum updateflags uflags = UF_AUTO_ERASE | UF_VERIFY; /* Flags for do_op() */
|
||||||
|
|
||||||
#if !defined(WIN32)
|
|
||||||
char * homedir;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
_set_printf_count_output(1);
|
_set_printf_count_output(1);
|
||||||
#endif
|
#endif
|
||||||
|
@ -856,14 +890,10 @@ int main(int argc, char * argv [])
|
||||||
win_usr_config_set(usr_config);
|
win_usr_config_set(usr_config);
|
||||||
#else
|
#else
|
||||||
usr_config[0] = 0;
|
usr_config[0] = 0;
|
||||||
homedir = getenv("HOME");
|
if(!concatpath(usr_config, getenv("XDG_CONFIG_HOME"), XDG_USER_CONF_FILE, sizeof usr_config))
|
||||||
if (homedir != NULL) {
|
concatpath(usr_config, getenv("HOME"), ".config/" XDG_USER_CONF_FILE, sizeof usr_config);
|
||||||
strcpy(usr_config, homedir);
|
if(stat(usr_config, &sb) < 0 || (sb.st_mode & S_IFREG) == 0)
|
||||||
i = strlen(usr_config);
|
concatpath(usr_config, getenv("HOME"), USER_CONF_FILE, sizeof usr_config);
|
||||||
if (i && (usr_config[i - 1] != '/'))
|
|
||||||
strcat(usr_config, "/");
|
|
||||||
strcat(usr_config, USER_CONF_FILE);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (quell_progress == 0)
|
if (quell_progress == 0)
|
||||||
|
@ -1190,9 +1220,10 @@ int main(int argc, char * argv [])
|
||||||
init_ok = (rc = pgm->initialize(pgm, p)) >= 0;
|
init_ok = (rc = pgm->initialize(pgm, p)) >= 0;
|
||||||
if (!init_ok) {
|
if (!init_ok) {
|
||||||
pmsg_error("initialization failed, rc=%d\n", rc);
|
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) {
|
if (!ovsigck) {
|
||||||
imsg_error("double check connections and try again or use -F to override\n");
|
imsg_error("- use -F to override this check\n\n");
|
||||||
imsg_error("this check\n\n");
|
|
||||||
exitrc = 1;
|
exitrc = 1;
|
||||||
goto main_exit;
|
goto main_exit;
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,6 +140,7 @@ PROGRAMMER *pgm_new(void) {
|
||||||
pgm->write_setup = NULL;
|
pgm->write_setup = NULL;
|
||||||
pgm->read_sig_bytes = NULL;
|
pgm->read_sig_bytes = NULL;
|
||||||
pgm->read_sib = NULL;
|
pgm->read_sib = NULL;
|
||||||
|
pgm->term_keep_alive= NULL;
|
||||||
pgm->print_parms = NULL;
|
pgm->print_parms = NULL;
|
||||||
pgm->set_vtarget = NULL;
|
pgm->set_vtarget = NULL;
|
||||||
pgm->set_varef = NULL;
|
pgm->set_varef = NULL;
|
||||||
|
|
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_getparm(const PROGRAMMER *pgm, unsigned parm, unsigned *value);
|
||||||
static int stk500_setparm(const PROGRAMMER *pgm, unsigned parm, unsigned value);
|
static int stk500_setparm(const PROGRAMMER *pgm, unsigned parm, unsigned value);
|
||||||
static void stk500_print_parms1(const PROGRAMMER *pgm, const char *p);
|
static void stk500_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp);
|
||||||
|
|
||||||
|
|
||||||
static int stk500_send(const PROGRAMMER *pgm, unsigned char *buf, size_t len) {
|
static int stk500_send(const PROGRAMMER *pgm, unsigned char *buf, size_t len) {
|
||||||
|
@ -625,6 +625,12 @@ static void stk500_disable(const PROGRAMMER *pgm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void stk500_enable(PROGRAMMER *pgm, const AVRPART *p) {
|
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;
|
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];
|
unsigned char buf[16];
|
||||||
int tries;
|
int tries;
|
||||||
unsigned char ext_byte;
|
unsigned char ext_byte;
|
||||||
OPCODE * lext;
|
|
||||||
|
addr /= a_div;
|
||||||
|
|
||||||
tries = 0;
|
tries = 0;
|
||||||
retry:
|
retry:
|
||||||
tries++;
|
tries++;
|
||||||
|
|
||||||
/* To support flash > 64K words the correct Extended Address Byte is needed */
|
// Support large flash by sending the correct extended address byte when needed
|
||||||
lext = mem->op[AVR_OP_LOAD_EXT_ADDR];
|
|
||||||
if (lext != NULL) {
|
if(pgm->prog_modes & PM_SPM) { // Bootloaders, eg, optiboot, optiboot_dx, optiboot_x
|
||||||
ext_byte = (addr >> 16) & 0xff;
|
if(mem->size/a_div > 64*1024) { // Extended addressing needed
|
||||||
if (ext_byte != PDATA(pgm)->ext_addr_byte) {
|
ext_byte = (addr >> 16) & 0xff;
|
||||||
/* Either this is the first addr load, or a different 64K word section */
|
if(ext_byte != PDATA(pgm)->ext_addr_byte) { // First addr load or a different 64k section
|
||||||
memset(buf, 0, 4);
|
buf[0] = 0x4d; // Protocol bytes that bootloaders expect
|
||||||
avr_set_bits(lext, buf);
|
buf[1] = 0x00;
|
||||||
avr_set_addr(lext, buf, addr);
|
buf[2] = ext_byte;
|
||||||
stk500_cmd(pgm, buf, buf);
|
buf[3] = 0x00;
|
||||||
PDATA(pgm)->ext_addr_byte = ext_byte;
|
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,
|
static int stk500_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
|
||||||
unsigned int page_size,
|
unsigned int page_size,
|
||||||
unsigned int addr, unsigned int n_bytes)
|
unsigned int addr, unsigned int n_bytes)
|
||||||
|
@ -736,25 +794,12 @@ static int stk500_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVR
|
||||||
unsigned int n;
|
unsigned int n;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
if (strcmp(m->desc, "flash") == 0) {
|
if(set_memtype_a_div(pgm, p, m, &memtype, &a_div) < 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 {
|
|
||||||
return -2;
|
return -2;
|
||||||
}
|
|
||||||
|
|
||||||
n = addr + n_bytes;
|
n = addr + n_bytes;
|
||||||
#if 0
|
#if 0
|
||||||
msg_info(
|
msg_debug(
|
||||||
"n_bytes = %d\n"
|
"n_bytes = %d\n"
|
||||||
"n = %u\n"
|
"n = %u\n"
|
||||||
"a_div = %d\n"
|
"a_div = %d\n"
|
||||||
|
@ -775,7 +820,7 @@ static int stk500_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVR
|
||||||
tries = 0;
|
tries = 0;
|
||||||
retry:
|
retry:
|
||||||
tries++;
|
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
|
/* build command block and avoid multiple send commands as it leads to a crash
|
||||||
of the silabs usb serial driver on mac os x */
|
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;
|
unsigned int n;
|
||||||
int block_size;
|
int block_size;
|
||||||
|
|
||||||
if (strcmp(m->desc, "flash") == 0) {
|
if(set_memtype_a_div(pgm, p, m, &memtype, &a_div) < 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 {
|
|
||||||
return -2;
|
return -2;
|
||||||
}
|
|
||||||
|
|
||||||
n = addr + n_bytes;
|
n = addr + n_bytes;
|
||||||
for (; addr < n; addr += block_size) {
|
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;
|
tries = 0;
|
||||||
retry:
|
retry:
|
||||||
tries++;
|
tries++;
|
||||||
stk500_loadaddr(pgm, m, addr/a_div);
|
stk500_loadaddr(pgm, m, addr, a_div);
|
||||||
buf[0] = Cmnd_STK_READ_PAGE;
|
buf[0] = Cmnd_STK_READ_PAGE;
|
||||||
buf[1] = (block_size >> 8) & 0xff;
|
buf[1] = (block_size >> 8) & 0xff;
|
||||||
buf[2] = block_size & 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);
|
msg_info("%sTopcard : %s\n", p, n);
|
||||||
}
|
}
|
||||||
if(strcmp(pgm->type, "Arduino") != 0)
|
if(strcmp(pgm->type, "Arduino") != 0)
|
||||||
stk500_print_parms1(pgm, p);
|
stk500_print_parms1(pgm, p, stderr);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void stk500_print_parms1(const PROGRAMMER *pgm, const char *p) {
|
static void stk500_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp) {
|
||||||
unsigned vtarget, vadjust, osc_pscale, osc_cmatch, sck_duration;
|
unsigned vtarget, vadjust, osc_pscale, osc_cmatch, sck_duration;
|
||||||
|
|
||||||
stk500_getparm(pgm, Parm_STK_VTARGET, &vtarget);
|
stk500_getparm(pgm, Parm_STK_VTARGET, &vtarget);
|
||||||
|
@ -1175,11 +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_OSC_CMATCH, &osc_cmatch);
|
||||||
stk500_getparm(pgm, Parm_STK_SCK_DURATION, &sck_duration);
|
stk500_getparm(pgm, Parm_STK_SCK_DURATION, &sck_duration);
|
||||||
|
|
||||||
msg_info("%sVtarget : %.1f V\n", p, vtarget / 10.0);
|
fmsg_out(fp, "%sVtarget : %.1f V\n", p, vtarget / 10.0);
|
||||||
msg_info("%sVaref : %.1f V\n", p, vadjust / 10.0);
|
fmsg_out(fp, "%sVaref : %.1f V\n", p, vadjust / 10.0);
|
||||||
msg_info("%sOscillator : ", p);
|
fmsg_out(fp, "%sOscillator : ", p);
|
||||||
if (osc_pscale == 0)
|
if (osc_pscale == 0)
|
||||||
msg_info("Off\n");
|
fmsg_out(fp, "Off\n");
|
||||||
else {
|
else {
|
||||||
int prescale = 1;
|
int prescale = 1;
|
||||||
double f = STK500_XTAL / 2;
|
double f = STK500_XTAL / 2;
|
||||||
|
@ -1203,16 +1235,16 @@ static void stk500_print_parms1(const PROGRAMMER *pgm, const char *p) {
|
||||||
unit = "kHz";
|
unit = "kHz";
|
||||||
} else
|
} else
|
||||||
unit = "Hz";
|
unit = "Hz";
|
||||||
msg_info("%.3f %s\n", f, unit);
|
fmsg_out(fp, "%.3f %s\n", f, unit);
|
||||||
}
|
}
|
||||||
msg_info("%sSCK period : %.1f us\n", p, sck_duration * 8.0e6 / STK500_XTAL + 0.05);
|
fmsg_out(fp, "%sSCK period : %.1f us\n", p, sck_duration * 8.0e6 / STK500_XTAL + 0.05);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void stk500_print_parms(const PROGRAMMER *pgm) {
|
static void stk500_print_parms(const PROGRAMMER *pgm, FILE *fp) {
|
||||||
stk500_print_parms1(pgm, "");
|
stk500_print_parms1(pgm, "", fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void stk500_setup(PROGRAMMER * pgm)
|
static void stk500_setup(PROGRAMMER * pgm)
|
||||||
|
|
|
@ -262,7 +262,7 @@ static int stk500v2_setparm(const PROGRAMMER *pgm, unsigned char parm, unsigned
|
||||||
static int stk500v2_getparm2(const PROGRAMMER *pgm, unsigned char parm, unsigned int *value);
|
static int stk500v2_getparm2(const PROGRAMMER *pgm, unsigned char parm, unsigned int *value);
|
||||||
static int stk500v2_setparm2(const PROGRAMMER *pgm, unsigned char parm, unsigned int value);
|
static int stk500v2_setparm2(const PROGRAMMER *pgm, unsigned char parm, unsigned int value);
|
||||||
static int stk500v2_setparm_real(const PROGRAMMER *pgm, unsigned char parm, unsigned char value);
|
static int stk500v2_setparm_real(const PROGRAMMER *pgm, unsigned char parm, unsigned char value);
|
||||||
static void stk500v2_print_parms1(const PROGRAMMER *pgm, const char *p);
|
static void stk500v2_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp);
|
||||||
static int stk500v2_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
|
static int stk500v2_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
|
||||||
unsigned int page_size,
|
unsigned int page_size,
|
||||||
unsigned int addr, unsigned int n_bytes);
|
unsigned int addr, unsigned int n_bytes);
|
||||||
|
@ -3075,7 +3075,7 @@ static void stk500v2_display(const PROGRAMMER *pgm, const char *p) {
|
||||||
stk500v2_getparm2(pgm, PARAM2_EC_ID_TABLE_REV, &rev);
|
stk500v2_getparm2(pgm, PARAM2_EC_ID_TABLE_REV, &rev);
|
||||||
msg_info("%sEC_ID table rev : %d\n", p, rev);
|
msg_info("%sEC_ID table rev : %d\n", p, rev);
|
||||||
}
|
}
|
||||||
stk500v2_print_parms1(pgm, p);
|
stk500v2_print_parms1(pgm, p, stderr);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -3095,7 +3095,7 @@ f_to_kHz_MHz(double f, const char **unit)
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void stk500v2_print_parms1(const PROGRAMMER *pgm, const char *p) {
|
static void stk500v2_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp) {
|
||||||
unsigned char vtarget = 0, vadjust = 0, osc_pscale = 0, osc_cmatch = 0, sck_duration =0; //XXX 0 is not correct, check caller
|
unsigned char vtarget = 0, vadjust = 0, osc_pscale = 0, osc_cmatch = 0, sck_duration =0; //XXX 0 is not correct, check caller
|
||||||
unsigned int sck_stk600, clock_conf, dac, oct, varef;
|
unsigned int sck_stk600, clock_conf, dac, oct, varef;
|
||||||
unsigned char vtarget_jtag[4];
|
unsigned char vtarget_jtag[4];
|
||||||
|
@ -3110,8 +3110,7 @@ static void stk500v2_print_parms1(const PROGRAMMER *pgm, const char *p) {
|
||||||
pgmcp->cookie = PDATA(pgm)->chained_pdata;
|
pgmcp->cookie = PDATA(pgm)->chained_pdata;
|
||||||
jtagmkII_getparm(pgmcp, PAR_OCD_VTARGET, vtarget_jtag);
|
jtagmkII_getparm(pgmcp, PAR_OCD_VTARGET, vtarget_jtag);
|
||||||
pgm_free(pgmcp);
|
pgm_free(pgmcp);
|
||||||
msg_info("%sVtarget : %.1f V\n", p,
|
fmsg_out(fp, "%sVtarget : %.1f V\n", p, b2_to_u16(vtarget_jtag) / 1000.0);
|
||||||
b2_to_u16(vtarget_jtag) / 1000.0);
|
|
||||||
} else if (PDATA(pgm)->pgmtype == PGMTYPE_JTAGICE3) {
|
} else if (PDATA(pgm)->pgmtype == PGMTYPE_JTAGICE3) {
|
||||||
PROGRAMMER *pgmcp = pgm_dup(pgm);
|
PROGRAMMER *pgmcp = pgm_dup(pgm);
|
||||||
pgmcp->cookie = PDATA(pgm)->chained_pdata;
|
pgmcp->cookie = PDATA(pgm)->chained_pdata;
|
||||||
|
@ -3119,11 +3118,11 @@ static void stk500v2_print_parms1(const PROGRAMMER *pgm, const char *p) {
|
||||||
// Copy pgm->id contents over to pgmcp->id
|
// Copy pgm->id contents over to pgmcp->id
|
||||||
for(LNODEID ln=lfirst(pgm->id); ln; ln=lnext(ln))
|
for(LNODEID ln=lfirst(pgm->id); ln; ln=lnext(ln))
|
||||||
ladd(pgmcp->id, cfg_strdup("stk500v2_print_parms1()", ldata(ln)));
|
ladd(pgmcp->id, cfg_strdup("stk500v2_print_parms1()", ldata(ln)));
|
||||||
jtag3_print_parms1(pgmcp, p);
|
jtag3_print_parms1(pgmcp, p, fp);
|
||||||
pgm_free(pgmcp);
|
pgm_free(pgmcp);
|
||||||
} else {
|
} else {
|
||||||
stk500v2_getparm(pgm, PARAM_VTARGET, &vtarget);
|
stk500v2_getparm(pgm, PARAM_VTARGET, &vtarget);
|
||||||
msg_info("%sVtarget : %.1f V\n", p, vtarget / 10.0);
|
fmsg_out(fp, "%sVtarget : %.1f V\n", p, vtarget / 10.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (PDATA(pgm)->pgmtype) {
|
switch (PDATA(pgm)->pgmtype) {
|
||||||
|
@ -3132,12 +3131,12 @@ static void stk500v2_print_parms1(const PROGRAMMER *pgm, const char *p) {
|
||||||
stk500v2_getparm(pgm, PARAM_VADJUST, &vadjust);
|
stk500v2_getparm(pgm, PARAM_VADJUST, &vadjust);
|
||||||
stk500v2_getparm(pgm, PARAM_OSC_PSCALE, &osc_pscale);
|
stk500v2_getparm(pgm, PARAM_OSC_PSCALE, &osc_pscale);
|
||||||
stk500v2_getparm(pgm, PARAM_OSC_CMATCH, &osc_cmatch);
|
stk500v2_getparm(pgm, PARAM_OSC_CMATCH, &osc_cmatch);
|
||||||
msg_info("%sSCK period : %.1f us\n", p,
|
fmsg_out(fp, "%sSCK period : %.1f us\n", p,
|
||||||
stk500v2_sck_to_us(pgm, sck_duration));
|
stk500v2_sck_to_us(pgm, sck_duration));
|
||||||
msg_info("%sVaref : %.1f V\n", p, vadjust / 10.0);
|
fmsg_out(fp, "%sVaref : %.1f V\n", p, vadjust / 10.0);
|
||||||
msg_info("%sOscillator : ", p);
|
fmsg_out(fp, "%sOscillator : ", p);
|
||||||
if (osc_pscale == 0)
|
if (osc_pscale == 0)
|
||||||
msg_info("Off\n");
|
fmsg_out(fp, "Off\n");
|
||||||
else {
|
else {
|
||||||
prescale = 1;
|
prescale = 1;
|
||||||
f = STK500V2_XTAL / 2;
|
f = STK500V2_XTAL / 2;
|
||||||
|
@ -3153,14 +3152,14 @@ static void stk500v2_print_parms1(const PROGRAMMER *pgm, const char *p) {
|
||||||
f /= prescale;
|
f /= prescale;
|
||||||
f /= (osc_cmatch + 1);
|
f /= (osc_cmatch + 1);
|
||||||
f = f_to_kHz_MHz(f, &unit);
|
f = f_to_kHz_MHz(f, &unit);
|
||||||
msg_info("%.3f %s\n", f, unit);
|
fmsg_out(fp, "%.3f %s\n", f, unit);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PGMTYPE_AVRISP_MKII:
|
case PGMTYPE_AVRISP_MKII:
|
||||||
case PGMTYPE_JTAGICE_MKII:
|
case PGMTYPE_JTAGICE_MKII:
|
||||||
stk500v2_getparm(pgm, PARAM_SCK_DURATION, &sck_duration);
|
stk500v2_getparm(pgm, PARAM_SCK_DURATION, &sck_duration);
|
||||||
msg_info("%sSCK period : %.2f us\n", p,
|
fmsg_out(fp, "%sSCK period : %.2f us\n", p,
|
||||||
(float) 1000000 / avrispmkIIfreqs[sck_duration]);
|
(float) 1000000 / avrispmkIIfreqs[sck_duration]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -3172,7 +3171,7 @@ static void stk500v2_print_parms1(const PROGRAMMER *pgm, const char *p) {
|
||||||
if (stk500v2_jtag3_send(pgm, cmd, 1) >= 0 &&
|
if (stk500v2_jtag3_send(pgm, cmd, 1) >= 0 &&
|
||||||
stk500v2_jtag3_recv(pgm, cmd, 4) >= 2) {
|
stk500v2_jtag3_recv(pgm, cmd, 4) >= 2) {
|
||||||
unsigned int sck = cmd[1] | (cmd[2] << 8);
|
unsigned int sck = cmd[1] | (cmd[2] << 8);
|
||||||
msg_info("%sSCK period : %.2f us\n", p,
|
fmsg_out(fp, "%sSCK period : %.2f us\n", p,
|
||||||
(float)(1E6 / (1000.0 * sck)));
|
(float)(1E6 / (1000.0 * sck)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3180,23 +3179,23 @@ static void stk500v2_print_parms1(const PROGRAMMER *pgm, const char *p) {
|
||||||
|
|
||||||
case PGMTYPE_STK600:
|
case PGMTYPE_STK600:
|
||||||
stk500v2_getparm2(pgm, PARAM2_AREF0, &varef);
|
stk500v2_getparm2(pgm, PARAM2_AREF0, &varef);
|
||||||
msg_info("%sVaref 0 : %.2f V\n", p, varef / 100.0);
|
fmsg_out(fp, "%sVaref 0 : %.2f V\n", p, varef / 100.0);
|
||||||
stk500v2_getparm2(pgm, PARAM2_AREF1, &varef);
|
stk500v2_getparm2(pgm, PARAM2_AREF1, &varef);
|
||||||
msg_info("%sVaref 1 : %.2f V\n", p, varef / 100.0);
|
fmsg_out(fp, "%sVaref 1 : %.2f V\n", p, varef / 100.0);
|
||||||
stk500v2_getparm2(pgm, PARAM2_SCK_DURATION, &sck_stk600);
|
stk500v2_getparm2(pgm, PARAM2_SCK_DURATION, &sck_stk600);
|
||||||
msg_info("%sSCK period : %.2f us\n", p,
|
fmsg_out(fp, "%sSCK period : %.2f us\n", p,
|
||||||
(float) (sck_stk600 + 1) / 8.0);
|
(float) (sck_stk600 + 1) / 8.0);
|
||||||
stk500v2_getparm2(pgm, PARAM2_CLOCK_CONF, &clock_conf);
|
stk500v2_getparm2(pgm, PARAM2_CLOCK_CONF, &clock_conf);
|
||||||
oct = (clock_conf & 0xf000) >> 12u;
|
oct = (clock_conf & 0xf000) >> 12u;
|
||||||
dac = (clock_conf & 0x0ffc) >> 2u;
|
dac = (clock_conf & 0x0ffc) >> 2u;
|
||||||
f = pow(2, (double)oct) * 2078.0 / (2 - (double)dac / 1024.0);
|
f = pow(2, (double)oct) * 2078.0 / (2 - (double)dac / 1024.0);
|
||||||
f = f_to_kHz_MHz(f, &unit);
|
f = f_to_kHz_MHz(f, &unit);
|
||||||
msg_info("%sOscillator : %.3f %s\n",
|
fmsg_out(fp, "%sOscillator : %.3f %s\n",
|
||||||
p, f, unit);
|
p, f, unit);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
msg_info("%sSCK period : %.1f us\n", p,
|
fmsg_out(fp, "%sSCK period : %.1f us\n", p,
|
||||||
sck_duration * 8.0e6 / STK500V2_XTAL + 0.05);
|
sck_duration * 8.0e6 / STK500V2_XTAL + 0.05);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -3205,8 +3204,8 @@ static void stk500v2_print_parms1(const PROGRAMMER *pgm, const char *p) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void stk500v2_print_parms(const PROGRAMMER *pgm) {
|
static void stk500v2_print_parms(const PROGRAMMER *pgm, FILE *fp) {
|
||||||
stk500v2_print_parms1(pgm, "");
|
stk500v2_print_parms1(pgm, "", fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int stk500v2_perform_osccal(const PROGRAMMER *pgm) {
|
static int stk500v2_perform_osccal(const PROGRAMMER *pgm) {
|
||||||
|
|
455
src/term.c
455
src/term.c
|
@ -33,10 +33,21 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#if defined(HAVE_LIBREADLINE)
|
#if defined(HAVE_LIBREADLINE)
|
||||||
# include <readline/readline.h>
|
#include <readline/readline.h>
|
||||||
# include <readline/history.h>
|
#include <readline/history.h>
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#include "msvc/unistd.h"
|
||||||
|
#else
|
||||||
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "avrdude.h"
|
#include "avrdude.h"
|
||||||
#include "term.h"
|
#include "term.h"
|
||||||
|
|
||||||
|
@ -114,7 +125,7 @@ static int nexttok(char *buf, char **tok, char **next) {
|
||||||
n = q;
|
n = q;
|
||||||
uint8_t quotes = 0;
|
uint8_t quotes = 0;
|
||||||
while (*n && (!isspace(*n) || quotes)) {
|
while (*n && (!isspace(*n) || quotes)) {
|
||||||
// poor man's quote and escape processing
|
// Poor man's quote and escape processing
|
||||||
if (*n == '"' || *n == '\'')
|
if (*n == '"' || *n == '\'')
|
||||||
quotes++;
|
quotes++;
|
||||||
else if(*n == '\\' && n[1])
|
else if(*n == '\\' && n[1])
|
||||||
|
@ -173,7 +184,7 @@ static int chardump_line(char *buffer, unsigned char *p, int n, int pad) {
|
||||||
int i;
|
int i;
|
||||||
unsigned char b[128];
|
unsigned char b[128];
|
||||||
|
|
||||||
// sanity check
|
// Sanity check
|
||||||
n = n < 1? 1: n > sizeof b? sizeof b: n;
|
n = n < 1? 1: n > sizeof b? sizeof b: n;
|
||||||
|
|
||||||
memcpy(b, p, n);
|
memcpy(b, p, n);
|
||||||
|
@ -202,7 +213,7 @@ static int hexdump_buf(FILE *f, int startaddr, unsigned char *buf, int len) {
|
||||||
n = len;
|
n = len;
|
||||||
hexdump_line(dst1, p, n, 48);
|
hexdump_line(dst1, p, n, 48);
|
||||||
chardump_line(dst2, p, n, 16);
|
chardump_line(dst2, p, n, 16);
|
||||||
fprintf(f, "%04x %s |%s|\n", addr, dst1, dst2);
|
term_out("%04x %s |%s|\n", addr, dst1, dst2);
|
||||||
len -= n;
|
len -= n;
|
||||||
addr += n;
|
addr += n;
|
||||||
p += n;
|
p += n;
|
||||||
|
@ -214,7 +225,7 @@ static int hexdump_buf(FILE *f, int startaddr, unsigned char *buf, int len) {
|
||||||
|
|
||||||
static int cmd_dump(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
static int cmd_dump(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
if (argc < 2 || argc > 4) {
|
if (argc < 2 || argc > 4) {
|
||||||
terminal_message(MSG_INFO,
|
msg_error(
|
||||||
"Usage: %s <memory> <addr> <len>\n"
|
"Usage: %s <memory> <addr> <len>\n"
|
||||||
" %s <memory> <addr> ...\n"
|
" %s <memory> <addr> ...\n"
|
||||||
" %s <memory> <addr>\n"
|
" %s <memory> <addr>\n"
|
||||||
|
@ -229,8 +240,7 @@ static int cmd_dump(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
char *memtype = argv[1];
|
char *memtype = argv[1];
|
||||||
AVRMEM *mem = avr_locate_mem(p, memtype);
|
AVRMEM *mem = avr_locate_mem(p, memtype);
|
||||||
if (mem == NULL) {
|
if (mem == NULL) {
|
||||||
terminal_message(MSG_INFO, "%s (dump): %s memory type not defined for part %s\n",
|
pmsg_error("(dump) %s memory type not defined for part %s\n", memtype, p->desc);
|
||||||
progname, memtype, p->desc);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
int maxsize = mem->size;
|
int maxsize = mem->size;
|
||||||
|
@ -242,12 +252,10 @@ static int cmd_dump(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
if (argc >= 3 && strcmp(argv[2], "...") != 0) {
|
if (argc >= 3 && strcmp(argv[2], "...") != 0) {
|
||||||
addr = strtoul(argv[2], &end_ptr, 0);
|
addr = strtoul(argv[2], &end_ptr, 0);
|
||||||
if (*end_ptr || (end_ptr == argv[2])) {
|
if (*end_ptr || (end_ptr == argv[2])) {
|
||||||
terminal_message(MSG_INFO, "%s (dump): can't parse address %s\n",
|
pmsg_error("(dump) cannot parse address %s\n", argv[2]);
|
||||||
progname, argv[2]);
|
|
||||||
return -1;
|
return -1;
|
||||||
} else if (addr < 0 || addr >= maxsize) {
|
} else if (addr < 0 || addr >= maxsize) {
|
||||||
terminal_message(MSG_INFO, "%s (dump): %s address 0x%05x is out of range [0, 0x%05x]\n",
|
pmsg_error("(dump) %s address 0x%05x is out of range [0, 0x%05x]\n", mem->desc, addr, maxsize-1);
|
||||||
progname, mem->desc, addr, maxsize-1);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -263,8 +271,7 @@ static int cmd_dump(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
} else if (argc == 4) {
|
} else if (argc == 4) {
|
||||||
len = strtol(argv[3], &end_ptr, 0);
|
len = strtol(argv[3], &end_ptr, 0);
|
||||||
if (*end_ptr || (end_ptr == argv[3])) {
|
if (*end_ptr || (end_ptr == argv[3])) {
|
||||||
terminal_message(MSG_INFO, "%s (dump): can't parse length %s\n",
|
pmsg_error("(dump) cannot parse length %s\n", argv[3]);
|
||||||
progname, argv[3]);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -288,7 +295,7 @@ static int cmd_dump(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
|
|
||||||
uint8_t *buf = malloc(len);
|
uint8_t *buf = malloc(len);
|
||||||
if (buf == NULL) {
|
if (buf == NULL) {
|
||||||
terminal_message(MSG_INFO, "%s (dump): out of memory\n", progname);
|
pmsg_error("(dump) out of memory\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,11 +304,9 @@ static int cmd_dump(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
int rc = pgm->read_byte_cached(pgm, p, mem, addr + i, &buf[i]);
|
int rc = pgm->read_byte_cached(pgm, p, mem, addr + i, &buf[i]);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
report_progress(1, -1, NULL);
|
report_progress(1, -1, NULL);
|
||||||
terminal_message(MSG_INFO, "%s (dump): error reading %s address 0x%05lx of part %s\n",
|
pmsg_error("(dump) error reading %s address 0x%05lx of part %s\n", mem->desc, (long) addr + i, p->desc);
|
||||||
progname, mem->desc, (long) addr + i, p->desc);
|
|
||||||
if (rc == -1)
|
if (rc == -1)
|
||||||
terminal_message(MSG_INFO, "%*sread operation not supported on memory type %s\n",
|
imsg_error("%*sread operation not supported on memory type %s\n", 7, "", mem->desc);
|
||||||
(int) strlen(progname)+9, "", mem->desc);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
report_progress(i, len, NULL);
|
report_progress(i, len, NULL);
|
||||||
|
@ -309,7 +314,7 @@ static int cmd_dump(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
report_progress(1, 1, NULL);
|
report_progress(1, 1, NULL);
|
||||||
|
|
||||||
hexdump_buf(stdout, addr, buf, len);
|
hexdump_buf(stdout, addr, buf, len);
|
||||||
fprintf(stdout, "\n");
|
term_out("\n");
|
||||||
|
|
||||||
free(buf);
|
free(buf);
|
||||||
|
|
||||||
|
@ -365,7 +370,7 @@ static int is_mantissa_only(char *p) {
|
||||||
|
|
||||||
static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
if (argc < 4) {
|
if (argc < 4) {
|
||||||
terminal_message(MSG_INFO,
|
msg_error(
|
||||||
"Usage: write <memory> <addr> <data>[,] {<data>[,]}\n"
|
"Usage: write <memory> <addr> <data>[,] {<data>[,]}\n"
|
||||||
" write <memory> <addr> <len> <data>[,] {<data>[,]} ...\n"
|
" write <memory> <addr> <len> <data>[,] {<data>[,]} ...\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
@ -399,14 +404,13 @@ static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
uint8_t write_mode; // Operation mode, "standard" or "fill"
|
uint8_t write_mode; // Operation mode, "standard" or "fill"
|
||||||
uint8_t start_offset; // Which argc argument
|
uint8_t start_offset; // Which argc argument
|
||||||
int len; // Number of bytes to write to memory
|
int len; // Number of bytes to write to memory
|
||||||
char *memtype = argv[1]; // Memory name string
|
char *memtype = argv[1]; // Memory name string
|
||||||
AVRMEM *mem = avr_locate_mem(p, memtype);
|
AVRMEM *mem = avr_locate_mem(p, memtype);
|
||||||
if (mem == NULL) {
|
if (mem == NULL) {
|
||||||
terminal_message(MSG_INFO, "%s (write): %s memory type not defined for part %s\n",
|
pmsg_error("(write) %s memory type not defined for part %s\n", memtype, p->desc);
|
||||||
progname, memtype, p->desc);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
int maxsize = mem->size;
|
int maxsize = mem->size;
|
||||||
|
@ -414,21 +418,19 @@ static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
char *end_ptr;
|
char *end_ptr;
|
||||||
int addr = strtoul(argv[2], &end_ptr, 0);
|
int addr = strtoul(argv[2], &end_ptr, 0);
|
||||||
if (*end_ptr || (end_ptr == argv[2])) {
|
if (*end_ptr || (end_ptr == argv[2])) {
|
||||||
terminal_message(MSG_INFO, "%s (write): can't parse address %s\n",
|
pmsg_error("(write) cannot parse address %s\n", argv[2]);
|
||||||
progname, argv[2]);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addr < 0 || addr >= maxsize) {
|
if (addr < 0 || addr >= maxsize) {
|
||||||
terminal_message(MSG_INFO, "%s (write): %s address 0x%05x is out of range [0, 0x%05x]\n",
|
pmsg_error("(write) %s address 0x%05x is out of range [0, 0x%05x]\n", mem->desc, addr, maxsize-1);
|
||||||
progname, mem->desc, addr, maxsize-1);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate a buffer guaranteed to be large enough
|
// Allocate a buffer guaranteed to be large enough
|
||||||
uint8_t *buf = calloc(mem->size + 8 + maxstrlen(argc-3, argv+3)+1, sizeof(uint8_t));
|
uint8_t *buf = calloc(mem->size + 8 + maxstrlen(argc-3, argv+3)+1, sizeof(uint8_t));
|
||||||
if (buf == NULL) {
|
if (buf == NULL) {
|
||||||
terminal_message(MSG_INFO, "%s (write): out of memory\n", progname);
|
pmsg_error("(write) out of memory\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -438,8 +440,7 @@ static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
start_offset = 4;
|
start_offset = 4;
|
||||||
len = strtoul(argv[3], &end_ptr, 0);
|
len = strtoul(argv[3], &end_ptr, 0);
|
||||||
if (*end_ptr || (end_ptr == argv[3])) {
|
if (*end_ptr || (end_ptr == argv[3])) {
|
||||||
terminal_message(MSG_INFO, "%s (write ...): can't parse length %s\n",
|
pmsg_error("(write ...) cannot parse length %s\n", argv[3]);
|
||||||
progname, argv[3]);
|
|
||||||
free(buf);
|
free(buf);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -471,8 +472,8 @@ static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
};
|
};
|
||||||
|
|
||||||
if(sizeof(long long) != sizeof(int64_t) || (data.a[0]^data.a[7]) != 1)
|
if(sizeof(long long) != sizeof(int64_t) || (data.a[0]^data.a[7]) != 1)
|
||||||
terminal_message(MSG_INFO, "%s (write): assumption on data types not met? "
|
pmsg_error("(write) assumption on data types not met? "
|
||||||
"Check source and recompile\n", progname);
|
"Check source and recompile\n");
|
||||||
bool is_big_endian = data.a[7];
|
bool is_big_endian = data.a[7];
|
||||||
|
|
||||||
for (i = start_offset; i < len + start_offset; i++) {
|
for (i = start_offset; i < len + start_offset; i++) {
|
||||||
|
@ -518,7 +519,7 @@ static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
bool is_out_of_range = 0;
|
bool is_out_of_range = 0;
|
||||||
int nhexdigs = p-argi-2;
|
int nhexdigs = p-argi-2;
|
||||||
|
|
||||||
if(is_signed) { // Is input in range for int64_t?
|
if(is_signed) { // Is input in range for int64_t?
|
||||||
errno = 0; (void) strtoll(argi, NULL, 0);
|
errno = 0; (void) strtoll(argi, NULL, 0);
|
||||||
is_outside_int64_t = errno == ERANGE;
|
is_outside_int64_t = errno == ERANGE;
|
||||||
}
|
}
|
||||||
|
@ -566,9 +567,8 @@ static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(is_outside_int64_t || is_out_of_range)
|
if(is_outside_int64_t || is_out_of_range)
|
||||||
terminal_message(MSG_INFO, "%s (write): %s out of int%d_t range, "
|
pmsg_error("(write) %s out of int%d_t range, "
|
||||||
"interpreted as %d-byte %lld; consider 'U' suffix\n",
|
"interpreted as %d-byte %lld; consider 'U' suffix\n", argi, data.size*8, data.size, (long long int) data.ll);
|
||||||
progname, argi, data.size*8, data.size, data.ll);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -583,8 +583,8 @@ static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
data.f = strtof(argi, &end_ptr);
|
data.f = strtof(argi, &end_ptr);
|
||||||
if (end_ptr != argi && toupper(*end_ptr) == 'F' && end_ptr[1] == 0)
|
if (end_ptr != argi && toupper(*end_ptr) == 'F' && end_ptr[1] == 0)
|
||||||
data.size = 4;
|
data.size = 4;
|
||||||
if (end_ptr != argi && *end_ptr == 0) // no suffix defaults to float but ...
|
if (end_ptr != argi && *end_ptr == 0) // No suffix defaults to float but ...
|
||||||
// ... do not accept valid mantissa-only floats that are integer rejects (eg, 078 or ULL overflows)
|
// ... do not accept valid mantissa-only floats that are integer rejects (eg, 078 or ULL overflows)
|
||||||
if (!is_mantissa_only(argi))
|
if (!is_mantissa_only(argi))
|
||||||
data.size = 4;
|
data.size = 4;
|
||||||
}
|
}
|
||||||
|
@ -593,29 +593,27 @@ static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
if ((*argi == '\'' && argi[arglen-1] == '\'') || (*argi == '\"' && argi[arglen-1] == '\"')) {
|
if ((*argi == '\'' && argi[arglen-1] == '\'') || (*argi == '\"' && argi[arglen-1] == '\"')) {
|
||||||
char *s = calloc(arglen-1, 1);
|
char *s = calloc(arglen-1, 1);
|
||||||
if (s == NULL) {
|
if (s == NULL) {
|
||||||
terminal_message(MSG_INFO, "%s (write str): out of memory\n", progname);
|
pmsg_error("(write str) out of memory\n");
|
||||||
free(buf);
|
free(buf);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
// Strip start and end quotes, and unescape C string
|
// Strip start and end quotes, and unescape C string
|
||||||
strncpy(s, argi+1, arglen-2);
|
strncpy(s, argi+1, arglen-2);
|
||||||
cfg_unescape(s, s);
|
cfg_unescape(s, s);
|
||||||
if (*argi == '\'') { // Single C-style character
|
if (*argi == '\'') { // Single C-style character
|
||||||
if(*s && s[1])
|
if(*s && s[1])
|
||||||
terminal_message(MSG_INFO, "%s (write): only using first character of %s\n",
|
pmsg_error("(write) only using first character of %s\n", argi);
|
||||||
progname, argi);
|
|
||||||
data.ll = *s;
|
data.ll = *s;
|
||||||
data.size = 1;
|
data.size = 1;
|
||||||
free(s);
|
free(s);
|
||||||
} else { // C-style string
|
} else { // C-style string
|
||||||
data.str_ptr = s;
|
data.str_ptr = s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!data.size && !data.str_ptr) {
|
if(!data.size && !data.str_ptr) {
|
||||||
terminal_message(MSG_INFO, "%s (write): can't parse data %s\n",
|
pmsg_error("(write) cannot parse data %s\n", argi);
|
||||||
progname, argi);
|
|
||||||
free(buf);
|
free(buf);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -644,8 +642,8 @@ static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
data.bytes_grown = 0;
|
data.bytes_grown = 0;
|
||||||
|
|
||||||
if ((addr + len + data.bytes_grown) > maxsize) {
|
if ((addr + len + data.bytes_grown) > maxsize) {
|
||||||
terminal_message(MSG_INFO, "%s (write): selected address and # bytes exceed "
|
pmsg_error("(write) selected address and # bytes exceed "
|
||||||
"range for %s memory\n", progname, memtype);
|
"range for %s memory\n", memtype);
|
||||||
free(buf);
|
free(buf);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -653,11 +651,11 @@ static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
if(data.str_ptr)
|
if(data.str_ptr)
|
||||||
free(data.str_ptr);
|
free(data.str_ptr);
|
||||||
|
|
||||||
terminal_message(MSG_NOTICE, "Info: writing %d bytes starting from address 0x%02lx",
|
pmsg_notice2("(write) writing %d bytes starting from address 0x%02lx",
|
||||||
len + data.bytes_grown, (long) addr);
|
len + data.bytes_grown, (long) addr);
|
||||||
if (write_mode == WRITE_MODE_FILL)
|
if (write_mode == WRITE_MODE_FILL)
|
||||||
terminal_message(MSG_NOTICE, "; remaining space filled with %s", argv[argc - 2]);
|
msg_notice2("; remaining space filled with %s", argv[argc - 2]);
|
||||||
terminal_message(MSG_NOTICE, "\n");
|
msg_notice2("\n");
|
||||||
|
|
||||||
pgm->err_led(pgm, OFF);
|
pgm->err_led(pgm, OFF);
|
||||||
bool werror = false;
|
bool werror = false;
|
||||||
|
@ -665,19 +663,16 @@ static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
for (i = 0; i < len + data.bytes_grown; i++) {
|
for (i = 0; i < len + data.bytes_grown; i++) {
|
||||||
int rc = pgm->write_byte_cached(pgm, p, mem, addr+i, buf[i]);
|
int rc = pgm->write_byte_cached(pgm, p, mem, addr+i, buf[i]);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
terminal_message(MSG_INFO, "%s (write): error writing 0x%02x at 0x%05lx, rc=%d\n",
|
pmsg_error("(write) error writing 0x%02x at 0x%05lx, rc=%d\n", buf[i], (long) addr+i, (int) rc);
|
||||||
progname, buf[i], (long) addr+i, (int) rc);
|
|
||||||
if (rc == -1)
|
if (rc == -1)
|
||||||
terminal_message(MSG_INFO, "%*swrite operation not supported on memory type %s\n",
|
imsg_error("%*swrite operation not supported on memory type %s\n", 8, "", mem->desc);
|
||||||
(int) strlen(progname)+10, "", mem->desc);
|
|
||||||
werror = true;
|
werror = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t b;
|
uint8_t b;
|
||||||
rc = pgm->read_byte_cached(pgm, p, mem, addr+i, &b);
|
rc = pgm->read_byte_cached(pgm, p, mem, addr+i, &b);
|
||||||
if (b != buf[i]) {
|
if (b != buf[i]) {
|
||||||
terminal_message(MSG_INFO, "%s (write): error writing 0x%02x at 0x%05lx cell=0x%02x\n",
|
pmsg_error("(write) error writing 0x%02x at 0x%05lx cell=0x%02x\n", buf[i], (long) addr+i, b);
|
||||||
progname, buf[i], (long) addr+i, b);
|
|
||||||
werror = true;
|
werror = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -713,14 +708,13 @@ static int cmd_send(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
if (spi_mode && (pgm->spi == NULL)) {
|
if (spi_mode && (pgm->spi == NULL)) {
|
||||||
terminal_message(MSG_INFO, "%s (send): the %s programmer does not support direct SPI transfers\n",
|
pmsg_error("(send) the %s programmer does not support direct SPI transfers\n", pgm->type);
|
||||||
progname, pgm->type);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ((argc > 5) || ((argc < 5) && (!spi_mode))) {
|
if ((argc > 5) || ((argc < 5) && (!spi_mode))) {
|
||||||
terminal_message(MSG_INFO, spi_mode?
|
msg_error(spi_mode?
|
||||||
"Usage: send <byte1> [<byte2> [<byte3> [<byte4>]]]\n":
|
"Usage: send <byte1> [<byte2> [<byte3> [<byte4>]]]\n":
|
||||||
"Usage: send <byte1> <byte2> <byte3> <byte4>\n");
|
"Usage: send <byte1> <byte2> <byte3> <byte4>\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -733,8 +727,7 @@ static int cmd_send(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
for (i=1; i<argc; i++) {
|
for (i=1; i<argc; i++) {
|
||||||
cmd[i-1] = strtoul(argv[i], &e, 0);
|
cmd[i-1] = strtoul(argv[i], &e, 0);
|
||||||
if (*e || (e == argv[i])) {
|
if (*e || (e == argv[i])) {
|
||||||
terminal_message(MSG_INFO, "%s (send): can't parse byte %s\n",
|
pmsg_error("(send) cannot parse byte %s\n", argv[i]);
|
||||||
progname, argv[i]);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -749,19 +742,17 @@ static int cmd_send(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
/*
|
/*
|
||||||
* display results
|
* display results
|
||||||
*/
|
*/
|
||||||
terminal_message(MSG_INFO, "results:");
|
term_out("results:");
|
||||||
for (i=0; i<len; i++)
|
for (i=0; i<len; i++)
|
||||||
terminal_message(MSG_INFO, " %02x", res[i]);
|
term_out(" %02x", res[i]);
|
||||||
terminal_message(MSG_INFO, "\n");
|
term_out("\n\n");
|
||||||
|
|
||||||
fprintf(stdout, "\n");
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int cmd_erase(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
static int cmd_erase(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
terminal_message(MSG_INFO, "%s: erasing chip\n", progname);
|
term_out("erasing chip ...\n");
|
||||||
// Erase chip and clear cache
|
// Erase chip and clear cache
|
||||||
pgm->chip_erase_cached(pgm, p);
|
pgm->chip_erase_cached(pgm, p);
|
||||||
|
|
||||||
|
@ -771,20 +762,18 @@ static int cmd_erase(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
|
|
||||||
static int cmd_pgerase(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
static int cmd_pgerase(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
if(argc < 3) {
|
if(argc < 3) {
|
||||||
terminal_message(MSG_INFO, "Usage: pgerase <memory> <addr>\n");
|
msg_error("Usage: pgerase <memory> <addr>\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *memtype = argv[1];
|
char *memtype = argv[1];
|
||||||
AVRMEM *mem = avr_locate_mem(p, memtype);
|
AVRMEM *mem = avr_locate_mem(p, memtype);
|
||||||
if(!mem) {
|
if(!mem) {
|
||||||
terminal_message(MSG_INFO, "%s (pgerase): %s memory type not defined for part %s\n",
|
pmsg_error("(pgerase) %s memory type not defined for part %s\n", memtype, p->desc);
|
||||||
progname, memtype, p->desc);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if(!avr_has_paged_access(pgm, mem)) {
|
if(!avr_has_paged_access(pgm, mem)) {
|
||||||
terminal_message(MSG_INFO, "%s (pgerase): %s memory cannot be paged addressed by %s\n",
|
pmsg_error("(pgerase) %s memory cannot be paged addressed by %s\n", memtype, (char *) ldata(lfirst(pgm->id)));
|
||||||
progname, memtype, ldata(lfirst(pgm->id)));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -793,21 +782,17 @@ static int cmd_pgerase(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
char *end_ptr;
|
char *end_ptr;
|
||||||
int addr = strtoul(argv[2], &end_ptr, 0);
|
int addr = strtoul(argv[2], &end_ptr, 0);
|
||||||
if(*end_ptr || (end_ptr == argv[2])) {
|
if(*end_ptr || (end_ptr == argv[2])) {
|
||||||
terminal_message(MSG_INFO, "%s (pgerase): can't parse address %s\n",
|
pmsg_error("(pgerase) cannot parse address %s\n", argv[2]);
|
||||||
progname, argv[2]);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addr < 0 || addr >= maxsize) {
|
if (addr < 0 || addr >= maxsize) {
|
||||||
terminal_message(MSG_INFO, "%s (pgerase): %s address 0x%05x is out of range [0, 0x%05x]\n",
|
pmsg_error("(pgerase) %s address 0x%05x is out of range [0, 0x%05x]\n", mem->desc, addr, maxsize-1);
|
||||||
progname, mem->desc, addr, maxsize-1);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// terminal_message(MSG_INFO, "%s: %s page erase 0x%05x\n", progname, mem->desc, addr & ~(mem->page_size-1));
|
|
||||||
if(pgm->page_erase_cached(pgm, p, mem, (unsigned int) addr) < 0) {
|
if(pgm->page_erase_cached(pgm, p, mem, (unsigned int) addr) < 0) {
|
||||||
terminal_message(MSG_INFO, "%s (pgerase): unable to erase %s page at 0x%05x\n",
|
pmsg_error("(pgerase) unable to erase %s page at 0x%05x\n", mem->desc, addr);
|
||||||
progname, mem->desc, addr);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -816,9 +801,9 @@ static int cmd_pgerase(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
|
|
||||||
|
|
||||||
static int cmd_part(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
static int cmd_part(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
fprintf(stdout, "\n");
|
term_out("\n");
|
||||||
avr_display(stdout, p, "", 0);
|
avr_display(stdout, p, "", 0);
|
||||||
fprintf(stdout, "\n");
|
term_out("\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -831,20 +816,18 @@ static int cmd_sig(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
|
|
||||||
rc = avr_signature(pgm, p);
|
rc = avr_signature(pgm, p);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
terminal_message(MSG_INFO, "%s (sig): error reading signature data, rc=%d\n",
|
pmsg_error("(sig) error reading signature data, rc=%d\n", rc);
|
||||||
progname, rc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m = avr_locate_mem(p, "signature");
|
m = avr_locate_mem(p, "signature");
|
||||||
if (m == NULL) {
|
if (m == NULL) {
|
||||||
terminal_message(MSG_INFO, "%s (sig): signature data not defined for device %s\n",
|
pmsg_error("(sig) signature data not defined for device %s\n", p->desc);
|
||||||
progname, p->desc);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fprintf(stdout, "Device signature = 0x");
|
term_out("Device signature = 0x");
|
||||||
for (i=0; i<m->size; i++)
|
for (i=0; i<m->size; i++)
|
||||||
fprintf(stdout, "%02x", m->buf[i]);
|
term_out("%02x", m->buf[i]);
|
||||||
fprintf(stdout, "\n\n");
|
term_out("\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -861,8 +844,8 @@ static int cmd_quit(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
|
|
||||||
|
|
||||||
static int cmd_parms(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
static int cmd_parms(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
pgm->print_parms(pgm);
|
pgm->print_parms(pgm, stdout);
|
||||||
terminal_message(MSG_INFO, "\n");
|
term_out("\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -873,18 +856,16 @@ static int cmd_vtarg(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
char *endp;
|
char *endp;
|
||||||
|
|
||||||
if (argc != 2) {
|
if (argc != 2) {
|
||||||
terminal_message(MSG_INFO, "Usage: vtarg <value>\n");
|
msg_error("Usage: vtarg <value>\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
v = strtod(argv[1], &endp);
|
v = strtod(argv[1], &endp);
|
||||||
if (endp == argv[1]) {
|
if (endp == argv[1]) {
|
||||||
terminal_message(MSG_INFO, "%s (vtarg): can't parse voltage %s\n",
|
pmsg_error("(vtarg) cannot parse voltage %s\n", argv[1]);
|
||||||
progname, argv[1]);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if ((rc = pgm->set_vtarget(pgm, v)) != 0) {
|
if ((rc = pgm->set_vtarget(pgm, v)) != 0) {
|
||||||
terminal_message(MSG_INFO, "%s (vtarg): unable to set V[target] (rc = %d)\n",
|
pmsg_error("(vtarg) unable to set V[target] (rc = %d)\n", rc);
|
||||||
progname, rc);
|
|
||||||
return -3;
|
return -3;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -897,7 +878,7 @@ static int cmd_fosc(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
char *endp;
|
char *endp;
|
||||||
|
|
||||||
if (argc != 2) {
|
if (argc != 2) {
|
||||||
terminal_message(MSG_INFO, "Usage: fosc <value>[M|k] | off\n");
|
msg_error("Usage: fosc <value>[M|k] | off\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
v = strtod(argv[1], &endp);
|
v = strtod(argv[1], &endp);
|
||||||
|
@ -905,8 +886,7 @@ static int cmd_fosc(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
if (strcmp(argv[1], "off") == 0)
|
if (strcmp(argv[1], "off") == 0)
|
||||||
v = 0.0;
|
v = 0.0;
|
||||||
else {
|
else {
|
||||||
terminal_message(MSG_INFO, "%s (fosc): can't parse frequency %s\n",
|
pmsg_error("(fosc) cannot parse frequency %s\n", argv[1]);
|
||||||
progname, argv[1]);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -915,8 +895,7 @@ static int cmd_fosc(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
else if (*endp == 'k' || *endp == 'K')
|
else if (*endp == 'k' || *endp == 'K')
|
||||||
v *= 1e3;
|
v *= 1e3;
|
||||||
if ((rc = pgm->set_fosc(pgm, v)) != 0) {
|
if ((rc = pgm->set_fosc(pgm, v)) != 0) {
|
||||||
terminal_message(MSG_INFO, "%s (fosc): unable to set oscillator frequency (rc = %d)\n",
|
pmsg_error("(fosc) unable to set oscillator frequency (rc = %d)\n", rc);
|
||||||
progname, rc);
|
|
||||||
return -3;
|
return -3;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -929,19 +908,17 @@ static int cmd_sck(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
char *endp;
|
char *endp;
|
||||||
|
|
||||||
if (argc != 2) {
|
if (argc != 2) {
|
||||||
terminal_message(MSG_INFO, "Usage: sck <value>\n");
|
msg_error("Usage: sck <value>\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
v = strtod(argv[1], &endp);
|
v = strtod(argv[1], &endp);
|
||||||
if (endp == argv[1]) {
|
if (endp == argv[1]) {
|
||||||
terminal_message(MSG_INFO, "%s (sck): can't parse period %s\n",
|
pmsg_error("(sck) cannot parse period %s\n", argv[1]);
|
||||||
progname, argv[1]);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
v *= 1e-6; /* Convert from microseconds to seconds. */
|
v *= 1e-6; // Convert from microseconds to seconds
|
||||||
if ((rc = pgm->set_sck_period(pgm, v)) != 0) {
|
if ((rc = pgm->set_sck_period(pgm, v)) != 0) {
|
||||||
terminal_message(MSG_INFO, "%s (sck): unable to set SCK period (rc = %d)\n",
|
pmsg_error("(sck) unable to set SCK period (rc = %d)\n", rc);
|
||||||
progname, rc);
|
|
||||||
return -3;
|
return -3;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -955,34 +932,30 @@ static int cmd_varef(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
char *endp;
|
char *endp;
|
||||||
|
|
||||||
if (argc != 2 && argc != 3) {
|
if (argc != 2 && argc != 3) {
|
||||||
terminal_message(MSG_INFO, "Usage: varef [channel] <value>\n");
|
msg_error("Usage: varef [channel] <value>\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (argc == 2) {
|
if (argc == 2) {
|
||||||
chan = 0;
|
chan = 0;
|
||||||
v = strtod(argv[1], &endp);
|
v = strtod(argv[1], &endp);
|
||||||
if (endp == argv[1]) {
|
if (endp == argv[1]) {
|
||||||
terminal_message(MSG_INFO, "%s (varef): can't parse voltage %s\n",
|
pmsg_error("(varef) cannot parse voltage %s\n", argv[1]);
|
||||||
progname, argv[1]);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
chan = strtoul(argv[1], &endp, 10);
|
chan = strtoul(argv[1], &endp, 10);
|
||||||
if (endp == argv[1]) {
|
if (endp == argv[1]) {
|
||||||
terminal_message(MSG_INFO, "%s (varef): can't parse channel %s\n",
|
pmsg_error("(varef) cannot parse channel %s\n", argv[1]);
|
||||||
progname, argv[1]);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
v = strtod(argv[2], &endp);
|
v = strtod(argv[2], &endp);
|
||||||
if (endp == argv[2]) {
|
if (endp == argv[2]) {
|
||||||
terminal_message(MSG_INFO, "%s (varef): can't parse voltage %s\n",
|
pmsg_error("(varef) cannot parse voltage %s\n", argv[2]);
|
||||||
progname, argv[2]);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((rc = pgm->set_varef(pgm, chan, v)) != 0) {
|
if ((rc = pgm->set_varef(pgm, chan, v)) != 0) {
|
||||||
terminal_message(MSG_INFO, "%s (varef): unable to set V[aref] (rc = %d)\n",
|
pmsg_error("(varef) unable to set V[aref] (rc = %d)\n", rc);
|
||||||
progname, rc);
|
|
||||||
return -3;
|
return -3;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -992,19 +965,19 @@ static int cmd_varef(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
static int cmd_help(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
static int cmd_help(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
fprintf(stdout, "Valid commands:\n");
|
term_out("Valid commands:\n");
|
||||||
for (i=0; i<NCMDS; i++) {
|
for (i=0; i<NCMDS; i++) {
|
||||||
if(!*(void (**)(void)) ((char *) pgm + cmd[i].fnoff))
|
if(!*(void (**)(void)) ((char *) pgm + cmd[i].fnoff))
|
||||||
continue;
|
continue;
|
||||||
fprintf(stdout, " %-7s : ", cmd[i].name);
|
term_out(" %-7s : ", cmd[i].name);
|
||||||
fprintf(stdout, cmd[i].desc, cmd[i].name);
|
term_out(cmd[i].desc, cmd[i].name);
|
||||||
fprintf(stdout, "\n");
|
term_out("\n");
|
||||||
}
|
}
|
||||||
fprintf(stdout, "\n"
|
term_out("\n"
|
||||||
"Note that not all programmer derivatives support all commands. Flash and\n"
|
"Note that not all programmer derivatives support all commands. Flash and\n"
|
||||||
"EEPROM type memories are normally read and written using a cache via paged\n"
|
"EEPROM type memories are normally read and written using a cache via paged\n"
|
||||||
"read and write access; the cache is synchronised on quit. Use the part\n"
|
"read and write access; the cache is synchronised on quit or flush commands.\n"
|
||||||
"command to display valid memory types for use with dump and write.\n\n");
|
"The part command displays valid memory types for use with dump and write.\n\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1026,26 +999,24 @@ static int cmd_verbose(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
char *endp;
|
char *endp;
|
||||||
|
|
||||||
if (argc != 1 && argc != 2) {
|
if (argc != 1 && argc != 2) {
|
||||||
terminal_message(MSG_INFO, "Usage: verbose [<value>]\n");
|
msg_error("Usage: verbose [<value>]\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (argc == 1) {
|
if (argc == 1) {
|
||||||
terminal_message(MSG_INFO, "Verbosity level: %d\n", verbose);
|
msg_error("Verbosity level: %d\n", verbose);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
nverb = strtol(argv[1], &endp, 0);
|
nverb = strtol(argv[1], &endp, 0);
|
||||||
if (endp == argv[1] || *endp) {
|
if (endp == argv[1] || *endp) {
|
||||||
terminal_message(MSG_INFO, "%s (verbose): can't parse verbosity level %s\n",
|
pmsg_error("(verbose) cannot parse verbosity level %s\n", argv[1]);
|
||||||
progname, argv[1]);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (nverb < 0) {
|
if (nverb < 0) {
|
||||||
terminal_message(MSG_INFO, "%s: verbosity level must not be negative: %d\n",
|
pmsg_error("(verbose) level must not be negative: %d\n", nverb);
|
||||||
progname, nverb);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
verbose = nverb;
|
verbose = nverb;
|
||||||
terminal_message(MSG_INFO, "New verbosity level: %d\n", verbose);
|
term_out("New verbosity level: %d\n", verbose);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1055,26 +1026,24 @@ static int cmd_quell(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
char *endp;
|
char *endp;
|
||||||
|
|
||||||
if (argc != 1 && argc != 2) {
|
if (argc != 1 && argc != 2) {
|
||||||
terminal_message(MSG_INFO, "Usage: quell [<value>]\n");
|
msg_error("Usage: quell [<value>]\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (argc == 1) {
|
if (argc == 1) {
|
||||||
terminal_message(MSG_INFO, "Quell level: %d\n", quell_progress);
|
msg_error("Quell level: %d\n", quell_progress);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
nquell = strtol(argv[1], &endp, 0);
|
nquell = strtol(argv[1], &endp, 0);
|
||||||
if (endp == argv[1] || *endp) {
|
if (endp == argv[1] || *endp) {
|
||||||
terminal_message(MSG_INFO, "%s (quell): can't parse quell level %s\n",
|
pmsg_error("(quell) cannot parse quell level %s\n", argv[1]);
|
||||||
progname, argv[1]);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (nquell < 0) {
|
if (nquell < 0) {
|
||||||
terminal_message(MSG_INFO, "%s: quell level must not be negative: %d\n",
|
pmsg_error("(quell) level must not be negative: %d\n", nquell);
|
||||||
progname, nquell);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
quell_progress = nquell;
|
quell_progress = nquell;
|
||||||
terminal_message(MSG_INFO, "New quell level: %d\n", quell_progress);
|
term_out("New quell level: %d\n", quell_progress);
|
||||||
|
|
||||||
if(quell_progress > 0)
|
if(quell_progress > 0)
|
||||||
update_progress = NULL;
|
update_progress = NULL;
|
||||||
|
@ -1195,8 +1164,7 @@ static int do_cmd(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
return cmd[i].func(pgm, p, argc, argv);
|
return cmd[i].func(pgm, p, argc, argv);
|
||||||
if (len && strncasecmp(argv[0], cmd[i].name, len)==0) {
|
if (len && strncasecmp(argv[0], cmd[i].name, len)==0) {
|
||||||
if (hold != -1) {
|
if (hold != -1) {
|
||||||
terminal_message(MSG_INFO, "%s (cmd): command %s is ambiguous\n",
|
pmsg_error("(cmd) command %s is ambiguous\n", argv[0]);
|
||||||
progname, argv[0]);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
hold = i;
|
hold = i;
|
||||||
|
@ -1206,104 +1174,177 @@ static int do_cmd(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||||
if (hold != -1)
|
if (hold != -1)
|
||||||
return cmd[hold].func(pgm, p, argc, argv);
|
return cmd[hold].func(pgm, p, argc, argv);
|
||||||
|
|
||||||
terminal_message(MSG_INFO, "%s (cmd): invalid command %s\n",
|
pmsg_error("(cmd) invalid command %s\n", argv[0]);
|
||||||
progname, argv[0]);
|
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char *terminal_get_input(const char *prompt) {
|
char *terminal_get_input(const char *prompt) {
|
||||||
#if defined(HAVE_LIBREADLINE) && !defined(WIN32)
|
|
||||||
char *input;
|
|
||||||
input = readline(prompt);
|
|
||||||
if ((input != NULL) && (strlen(input) >= 1))
|
|
||||||
add_history(input);
|
|
||||||
|
|
||||||
return input;
|
|
||||||
#else
|
|
||||||
char input[256];
|
char input[256];
|
||||||
fprintf(stdout, "%s", prompt);
|
|
||||||
if (fgets(input, sizeof(input), stdin))
|
term_out("%s", prompt);
|
||||||
{
|
if(fgets(input, sizeof(input), stdin)) {
|
||||||
/* FIXME: readline strips the '\n', should this too? */
|
int len = strlen(input);
|
||||||
return strdup(input);
|
if(len > 0 && input[len-1] == '\n')
|
||||||
|
input[len-1] = 0;
|
||||||
|
return cfg_strdup(__func__, input);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
return NULL;
|
return NULL;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int terminal_mode(PROGRAMMER *pgm, AVRPART *p) {
|
static int process_line(char *cmdbuf, PROGRAMMER *pgm, struct avrpart *p) {
|
||||||
char *cmdbuf;
|
int argc, rc;
|
||||||
char *q;
|
char **argv = NULL, *q;
|
||||||
int rc;
|
|
||||||
int argc;
|
|
||||||
char **argv;
|
|
||||||
|
|
||||||
rc = 0;
|
// Find the start of the command, skipping any white space
|
||||||
while ((cmdbuf = terminal_get_input("avrdude> ")) != NULL) {
|
q = cmdbuf;
|
||||||
/*
|
while(*q && isspace((unsigned char) *q))
|
||||||
* find the start of the command, skipping any white space
|
q++;
|
||||||
*/
|
|
||||||
q = cmdbuf;
|
|
||||||
while (*q && isspace((unsigned char) *q))
|
|
||||||
q++;
|
|
||||||
|
|
||||||
/* skip blank lines and comments */
|
// Skip blank lines and comments
|
||||||
if (!*q || (*q == '#'))
|
if (!*q || (*q == '#'))
|
||||||
continue;
|
return 0;
|
||||||
|
|
||||||
/* tokenize command line */
|
// Tokenize command line
|
||||||
argc = tokenize(q, &argv);
|
argc = tokenize(q, &argv);
|
||||||
if (argc < 0) {
|
|
||||||
free(cmdbuf);
|
if(!argv)
|
||||||
return argc;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(HAVE_LIBREADLINE) || defined(WIN32) || defined(__APPLE__)
|
#if !defined(HAVE_LIBREADLINE) || defined(WIN32) || defined(__APPLE__)
|
||||||
fprintf(stdout, ">>> ");
|
term_out(">>> ");
|
||||||
for (int i=0; i<argc; i++)
|
for (int i=0; i<argc; i++)
|
||||||
fprintf(stdout, "%s ", argv[i]);
|
term_out("%s ", argv[i]);
|
||||||
fprintf(stdout, "\n");
|
term_out("\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* run the command */
|
// Run the command
|
||||||
rc = do_cmd(pgm, p, argc, argv);
|
rc = do_cmd(pgm, p, argc, argv);
|
||||||
free(argv);
|
free(argv);
|
||||||
if (rc > 0) {
|
|
||||||
rc = 0;
|
return rc;
|
||||||
break;
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(HAVE_LIBREADLINE)
|
||||||
|
|
||||||
|
static PROGRAMMER *term_pgm;
|
||||||
|
static struct avrpart *term_p;
|
||||||
|
|
||||||
|
static int term_running;
|
||||||
|
|
||||||
|
// Any character in standard input available (without sleeping)?
|
||||||
|
static int readytoread() {
|
||||||
|
#ifdef WIN32
|
||||||
|
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
INPUT_RECORD input[1] = { 0 };
|
||||||
|
DWORD dwNumberOfEventsRead = 0;
|
||||||
|
|
||||||
|
if(!PeekConsoleInputA(hStdin, input, ARRAYSIZE(input), &dwNumberOfEventsRead)) {
|
||||||
|
DWORD dwError = GetLastError();
|
||||||
|
|
||||||
|
// Stdin redirected from a pipe or file (FIXME: reading from a pipe may sleep)
|
||||||
|
if(dwError == ERROR_INVALID_HANDLE)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
pmsg_warning("PeekConsoleInputA() failed with error code %u\n", (unsigned int) dwError);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(dwNumberOfEventsRead <= 0) // Nothing in the input buffer
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Filter out all the events that readline does not handle ...
|
||||||
|
if((input[0].EventType & KEY_EVENT) != 0 && input[0].Event.KeyEvent.bKeyDown)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
// Drain other events not handled by readline
|
||||||
|
if(!ReadConsoleInputA(hStdin, input, ARRAYSIZE(input), &dwNumberOfEventsRead)) {
|
||||||
|
pmsg_warning("ReadConsoleInputA() failed with error code %u\n", (unsigned int) GetLastError());
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
free(cmdbuf);
|
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
struct timeval tv = { 0L, 0L };
|
||||||
|
fd_set fds;
|
||||||
|
FD_ZERO(&fds);
|
||||||
|
FD_SET(0, &fds);
|
||||||
|
|
||||||
pgm->flush_cache(pgm, p);
|
return select(1, &fds, NULL, NULL, &tv) > 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
return rc;
|
// Callback processes commands whenever readline() has finished
|
||||||
|
void term_gotline(char *cmdstr) {
|
||||||
|
if(cmdstr) {
|
||||||
|
if(*cmdstr) {
|
||||||
|
add_history(cmdstr);
|
||||||
|
// only quit/abort returns a value > 0
|
||||||
|
if(process_line(cmdstr, term_pgm, term_p) > 0)
|
||||||
|
term_running = 0;
|
||||||
|
}
|
||||||
|
free(cmdstr);
|
||||||
|
} else {
|
||||||
|
// call quit at end of file or terminal ^D
|
||||||
|
term_out("\n");
|
||||||
|
cmd_quit(term_pgm, term_p, 0, NULL);
|
||||||
|
term_running = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int terminal_message(const int msglvl, const char *format, ...) {
|
int terminal_mode(PROGRAMMER *pgm, struct avrpart *p) {
|
||||||
|
term_pgm = pgm; // For callback routine
|
||||||
|
term_p = p;
|
||||||
|
|
||||||
|
rl_callback_handler_install("avrdude> ", term_gotline);
|
||||||
|
|
||||||
|
term_running = 1;
|
||||||
|
for(int n=1; term_running; n++) {
|
||||||
|
if(n%16 == 0) { // Every 100 ms (16*6.25 us) reset bootloader watchdog timer
|
||||||
|
if(pgm->term_keep_alive)
|
||||||
|
pgm->term_keep_alive(pgm, NULL);
|
||||||
|
}
|
||||||
|
usleep(6250);
|
||||||
|
if(readytoread() > 0 && term_running)
|
||||||
|
rl_callback_read_char();
|
||||||
|
}
|
||||||
|
|
||||||
|
rl_callback_handler_remove();
|
||||||
|
|
||||||
|
return pgm->flush_cache(pgm, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
|
||||||
|
int terminal_mode(PROGRAMMER *pgm, struct avrpart *p) {
|
||||||
|
char *cmdbuf;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
fflush(stdout); fflush(stderr);
|
while((cmdbuf = terminal_get_input("avrdude> "))) {
|
||||||
if (verbose >= msglvl) {
|
int rc = process_line(cmdbuf, pgm, p);
|
||||||
va_start(ap, format);
|
free(cmdbuf);
|
||||||
rc = vfprintf(stderr, format, ap);
|
if(rc > 0)
|
||||||
va_end(ap);
|
break;
|
||||||
}
|
}
|
||||||
fflush(stderr);
|
|
||||||
|
|
||||||
return rc;
|
if(rc <= 0)
|
||||||
|
cmd_quit(pgm, p, 0, NULL);
|
||||||
|
return pgm->flush_cache(pgm, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
static void update_progress_tty(int percent, double etime, const char *hdr, int finish) {
|
static void update_progress_tty(int percent, double etime, const char *hdr, int finish) {
|
||||||
static char *header;
|
static char *header;
|
||||||
static int last, done;
|
static int last, done = 1;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
setvbuf(stderr, (char *) NULL, _IONBF, 0);
|
setvbuf(stderr, (char *) NULL, _IONBF, 0);
|
||||||
|
@ -1330,7 +1371,7 @@ static void update_progress_tty(int percent, double etime, const char *hdr, int
|
||||||
hashes[i/2] = '#';
|
hashes[i/2] = '#';
|
||||||
hashes[50] = 0;
|
hashes[50] = 0;
|
||||||
|
|
||||||
msg_info("\r%s | %s | %d%% %0.2fs", header, hashes, showperc, etime);
|
msg_info("\r%s | %s | %d%% %0.2f s ", header, hashes, showperc, etime);
|
||||||
if(percent == 100) {
|
if(percent == 100) {
|
||||||
if(finish)
|
if(finish)
|
||||||
msg_info("\n\n");
|
msg_info("\n\n");
|
||||||
|
@ -1343,7 +1384,7 @@ static void update_progress_tty(int percent, double etime, const char *hdr, int
|
||||||
}
|
}
|
||||||
|
|
||||||
static void update_progress_no_tty(int percent, double etime, const char *hdr, int finish) {
|
static void update_progress_no_tty(int percent, double etime, const char *hdr, int finish) {
|
||||||
static int last, done;
|
static int last, done = 1;
|
||||||
|
|
||||||
setvbuf(stderr, (char *) NULL, _IONBF, 0);
|
setvbuf(stderr, (char *) NULL, _IONBF, 0);
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,6 @@ typedef enum {
|
||||||
int terminal_mode(PROGRAMMER * pgm, struct avrpart * p);
|
int terminal_mode(PROGRAMMER * pgm, struct avrpart * p);
|
||||||
char * terminal_get_input(const char *prompt);
|
char * terminal_get_input(const char *prompt);
|
||||||
void terminal_setup_update_progress();
|
void terminal_setup_update_progress();
|
||||||
int terminal_message(const int msglvl, const char *format, ...);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
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) {
|
static void ioerror(const char *iotype, UPDATE *upd) {
|
||||||
int errnocp = errno;
|
int errnocp = errno;
|
||||||
|
|
||||||
pmsg_ext_error("file %s is not %s", update_outname(upd->filename), iotype);
|
pmsg_ext_error("file %s is not %s: ", update_outname(upd->filename), iotype);
|
||||||
if(errnocp)
|
if(errnocp)
|
||||||
msg_ext_error("memstats(): %s", strerror(errnocp));
|
msg_ext_error("%s", strerror(errnocp));
|
||||||
else if(upd->filename && *upd->filename)
|
else if(upd->filename && *upd->filename)
|
||||||
msg_ext_error(" (not a regular or character file?)");
|
msg_ext_error("(not a regular or character file?)");
|
||||||
msg_ext_error("\n");
|
msg_ext_error("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -456,7 +456,8 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
|
||||||
}
|
}
|
||||||
pmsg_info("reading %s%s memory ...\n", mem->desc, alias_mem_desc);
|
pmsg_info("reading %s%s memory ...\n", mem->desc, alias_mem_desc);
|
||||||
|
|
||||||
report_progress(0, 1, "Reading");
|
if(mem->size > 32 || verbose > 1)
|
||||||
|
report_progress(0, 1, "Reading");
|
||||||
|
|
||||||
rc = avr_read(pgm, p, upd->memtype, 0);
|
rc = avr_read(pgm, p, upd->memtype, 0);
|
||||||
report_progress(1, 1, NULL);
|
report_progress(1, 1, NULL);
|
||||||
|
@ -511,7 +512,8 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
|
||||||
update_plural(fs.nbytes), mem->desc, alias_mem_desc);
|
update_plural(fs.nbytes), mem->desc, alias_mem_desc);
|
||||||
|
|
||||||
if (!(flags & UF_NOWRITE)) {
|
if (!(flags & UF_NOWRITE)) {
|
||||||
report_progress(0, 1, "Writing");
|
if(mem->size > 32 || verbose > 1)
|
||||||
|
report_progress(0, 1, "Writing");
|
||||||
rc = avr_write(pgm, p, upd->memtype, size, (flags & UF_AUTO_ERASE) != 0);
|
rc = avr_write(pgm, p, upd->memtype, size, (flags & UF_AUTO_ERASE) != 0);
|
||||||
report_progress(1, 1, NULL);
|
report_progress(1, 1, NULL);
|
||||||
} else {
|
} else {
|
||||||
|
@ -569,7 +571,8 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
|
||||||
pmsg_notice2("reading on-chip %s%s data ...\n", mem->desc, alias_mem_desc);
|
pmsg_notice2("reading on-chip %s%s data ...\n", mem->desc, alias_mem_desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
report_progress (0,1,"Reading");
|
if(mem->size > 32 || verbose > 1)
|
||||||
|
report_progress (0,1,"Reading");
|
||||||
rc = avr_read(pgm, p, upd->memtype, v);
|
rc = avr_read(pgm, p, upd->memtype, v);
|
||||||
report_progress (1,1,NULL);
|
report_progress (1,1,NULL);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
|
|
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
|
* right-to-left, so only the least significant nibbles need to be
|
||||||
* specified.
|
* specified.
|
||||||
*/
|
*/
|
||||||
if ((serno = strchr(port, ':')) != NULL)
|
if ((serno = strchr(port, ':')) != NULL) {
|
||||||
{
|
/* First, drop all colons there if any */
|
||||||
/* first, drop all colons there if any */
|
cp2 = ++serno;
|
||||||
cp2 = ++serno;
|
|
||||||
|
|
||||||
while ((cp2 = strchr(cp2, ':')) != NULL)
|
while ((cp2 = strchr(cp2, ':')) != NULL) {
|
||||||
{
|
x = strlen(cp2) - 1;
|
||||||
x = strlen(cp2) - 1;
|
memmove(cp2, cp2 + 1, x);
|
||||||
memmove(cp2, cp2 + 1, x);
|
cp2[x] = '\0';
|
||||||
cp2[x] = '\0';
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (strlen(serno) > 12)
|
if (strlen(serno) > 12) {
|
||||||
{
|
pmsg_error("invalid serial number %s\n", serno);
|
||||||
pmsg_error("invalid serial number %s\n", serno);
|
return -1;
|
||||||
return -1;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
wchar_t wserno[15];
|
wchar_t wserno[15];
|
||||||
mbstowcs(wserno, serno, 15);
|
mbstowcs(wserno, serno, 15);
|
||||||
size_t serlen = strlen(serno);
|
size_t serlen = strlen(serno);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now, try finding all devices matching VID:PID, and compare
|
* Now, try finding all devices matching VID:PID, and compare
|
||||||
* their serial numbers against the requested one.
|
* their serial numbers against the requested one.
|
||||||
*/
|
*/
|
||||||
struct hid_device_info *list, *walk;
|
struct hid_device_info *list, *walk;
|
||||||
list = hid_enumerate(pinfo.usbinfo.vid, pinfo.usbinfo.pid);
|
list = hid_enumerate(pinfo.usbinfo.vid, pinfo.usbinfo.pid);
|
||||||
if (list == NULL)
|
if (list == NULL) {
|
||||||
return -1;
|
pmsg_error("No USB HID devices found\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
walk = list;
|
walk = list;
|
||||||
while (walk)
|
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);
|
/* Found matching serial number */
|
||||||
size_t slen = wcslen(walk->serial_number);
|
break;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
if (walk == NULL)
|
pmsg_debug("usbhid_open(): serial number does not match\n");
|
||||||
{
|
walk = walk->next;
|
||||||
pmsg_error("no matching device found\n");
|
}
|
||||||
hid_free_enumeration(list);
|
if (walk == NULL) {
|
||||||
return -1;
|
pmsg_error("no matching device found\n");
|
||||||
}
|
|
||||||
pmsg_debug("usbhid_open(): opening path %s\n", walk->path);
|
|
||||||
dev = hid_open_path(walk->path);
|
|
||||||
hid_free_enumeration(list);
|
hid_free_enumeration(list);
|
||||||
if (dev == NULL)
|
return -1;
|
||||||
{
|
|
||||||
pmsg_error("found device, but hid_open_path() failed\n");
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
/*
|
pmsg_warning("USB device with VID: 0x%04x and PID: 0x%04x not found\n",
|
||||||
* No serial number requested, pass straight to hid_open()
|
pinfo.usbinfo.vid, pinfo.usbinfo.pid);
|
||||||
*/
|
return -1;
|
||||||
dev = hid_open(pinfo.usbinfo.vid, pinfo.usbinfo.pid, NULL);
|
|
||||||
if (dev == NULL)
|
|
||||||
{
|
|
||||||
pmsg_error("no device found\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fd->usb.handle = dev;
|
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
|
* be incremented by one, as the report ID will be omitted by the
|
||||||
* hidapi library.
|
* hidapi library.
|
||||||
*/
|
*/
|
||||||
if (pinfo.usbinfo.vid == USB_VENDOR_ATMEL)
|
if (pinfo.usbinfo.vid == USB_VENDOR_ATMEL) {
|
||||||
{
|
pmsg_debug("usbhid_open(): probing for max packet size\n");
|
||||||
pmsg_debug("usbhid_open(): probing for max packet size\n");
|
memset(usbbuf, 0, sizeof usbbuf);
|
||||||
memset(usbbuf, 0, sizeof usbbuf);
|
usbbuf[0] = 0; /* no HID reports used */
|
||||||
usbbuf[0] = 0; /* no HID reports used */
|
usbbuf[1] = 0; /* DAP_Info */
|
||||||
usbbuf[1] = 0; /* DAP_Info */
|
usbbuf[2] = 0xFF; /* get max. packet size */
|
||||||
usbbuf[2] = 0xFF; /* get max. packet size */
|
|
||||||
|
|
||||||
hid_write(dev, usbbuf, 65);
|
hid_write(dev, usbbuf, 65);
|
||||||
fd->usb.max_xfer = 64; /* first guess */
|
fd->usb.max_xfer = 64; /* first guess */
|
||||||
|
|
||||||
memset(usbbuf, 0, sizeof usbbuf);
|
memset(usbbuf, 0, sizeof usbbuf);
|
||||||
int res = hid_read_timeout(dev, usbbuf, 10 /* bytes */, 50 /* milliseconds */);
|
int res = hid_read_timeout(dev, usbbuf, 10 /* bytes */, 50 /* milliseconds */);
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
/* no timely response, assume 512 byte size */
|
/* No timely response, assume 512 byte size */
|
||||||
hid_write(dev, usbbuf, (512 - 64) + 1);
|
hid_write(dev, usbbuf, (512 - 64) + 1);
|
||||||
fd->usb.max_xfer = 512;
|
fd->usb.max_xfer = 512;
|
||||||
res = hid_read_timeout(dev, usbbuf, 10, 50);
|
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 (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) {
|
if (fd->usb.max_xfer > USBDEV_MAX_XFER_3) {
|
||||||
pmsg_error("unexpected max size %d, reducing to %d\n",
|
pmsg_error("unexpected max size %d, reducing to %d\n",
|
||||||
fd->usb.max_xfer, USBDEV_MAX_XFER_3);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usbhid_close(union filedescriptor *fd)
|
static void usbhid_close(union filedescriptor *fd) {
|
||||||
{
|
|
||||||
hid_device *udev = (hid_device *)fd->usb.handle;
|
hid_device *udev = (hid_device *)fd->usb.handle;
|
||||||
|
|
||||||
if (udev == NULL)
|
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;
|
hid_device *udev = (hid_device *)fd->usb.handle;
|
||||||
int rv;
|
int rv;
|
||||||
int i = mlen;
|
int i = mlen;
|
||||||
const unsigned char * p = bp;
|
const unsigned char * p = bp;
|
||||||
unsigned char usbbuf[USBDEV_MAX_XFER_3 + 1];
|
unsigned char usbbuf[USBDEV_MAX_XFER_3 + 1];
|
||||||
|
|
||||||
|
|
||||||
int tx_size;
|
int tx_size;
|
||||||
|
|
||||||
if (udev == NULL)
|
if (udev == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
tx_size = (mlen < USBDEV_MAX_XFER_3)? mlen: USBDEV_MAX_XFER_3;
|
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);
|
memcpy(usbbuf + 1, bp, tx_size);
|
||||||
rv = hid_write(udev, usbbuf, tx_size + 1);
|
rv = hid_write(udev, usbbuf, tx_size + 1);
|
||||||
if (rv < 0) {
|
if (rv < 0) {
|
||||||
|
@ -244,30 +232,26 @@ static int usbhid_send(const union filedescriptor *fd, const unsigned char *bp,
|
||||||
if (rv != tx_size + 1)
|
if (rv != tx_size + 1)
|
||||||
pmsg_error("short write to USB: %d bytes out of %d written\n", rv, tx_size + 1);
|
pmsg_error("short write to USB: %d bytes out of %d written\n", rv, tx_size + 1);
|
||||||
|
|
||||||
if (verbose > 4)
|
if (verbose > 4) {
|
||||||
{
|
pmsg_trace2("sent: ");
|
||||||
pmsg_trace2("sent: ");
|
|
||||||
|
|
||||||
while (i) {
|
while (i) {
|
||||||
unsigned char c = *p;
|
unsigned char c = *p;
|
||||||
if (isprint(c)) {
|
if (isprint(c))
|
||||||
msg_trace2("%c ", c);
|
msg_trace2("%c ", c);
|
||||||
}
|
else
|
||||||
else {
|
msg_trace2(". ");
|
||||||
msg_trace2(". ");
|
msg_trace2("[%02x] ", c);
|
||||||
}
|
|
||||||
msg_trace2("[%02x] ", c);
|
|
||||||
|
|
||||||
p++;
|
p++;
|
||||||
i--;
|
i--;
|
||||||
}
|
}
|
||||||
msg_trace2("\n");
|
msg_trace2("\n");
|
||||||
}
|
}
|
||||||
return 0;
|
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;
|
hid_device *udev = (hid_device *)fd->usb.handle;
|
||||||
int i, rv;
|
int i, rv;
|
||||||
unsigned char * p = buf;
|
unsigned char * p = buf;
|
||||||
|
@ -279,31 +263,26 @@ static int usbhid_recv(const union filedescriptor *fd, unsigned char *buf, size_
|
||||||
if (i != nbytes)
|
if (i != nbytes)
|
||||||
pmsg_error("short read, read only %d out of %lu bytes\n", i, (unsigned long) nbytes);
|
pmsg_error("short read, read only %d out of %lu bytes\n", i, (unsigned long) nbytes);
|
||||||
|
|
||||||
if (verbose > 4)
|
if (verbose > 4) {
|
||||||
{
|
pmsg_trace2("recv: ");
|
||||||
pmsg_trace2("recv: ");
|
|
||||||
|
|
||||||
while (i) {
|
while (i) {
|
||||||
unsigned char c = *p;
|
unsigned char c = *p;
|
||||||
if (isprint(c)) {
|
if (isprint(c))
|
||||||
msg_trace2("%c ", c);
|
msg_trace2("%c ", c);
|
||||||
}
|
else
|
||||||
else {
|
msg_trace2(". ");
|
||||||
msg_trace2(". ");
|
msg_trace2("[%02x] ", c);
|
||||||
}
|
|
||||||
msg_trace2("[%02x] ", c);
|
|
||||||
|
|
||||||
p++;
|
p++;
|
||||||
i--;
|
i--;
|
||||||
}
|
}
|
||||||
msg_trace2("\n");
|
msg_trace2("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
return rv;
|
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
|
* There is not much point in trying to flush any data
|
||||||
* on an USB endpoint, as the endpoint is supposed to
|
* 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.
|
* Device descriptor.
|
||||||
*/
|
*/
|
||||||
struct serial_device usbhid_serdev =
|
struct serial_device usbhid_serdev = {
|
||||||
{
|
|
||||||
.open = usbhid_open,
|
.open = usbhid_open,
|
||||||
.close = usbhid_close,
|
.close = usbhid_close,
|
||||||
.send = usbhid_send,
|
.send = usbhid_send,
|
||||||
|
|
|
@ -25,19 +25,28 @@
|
||||||
#ifndef usbdevs_h
|
#ifndef usbdevs_h
|
||||||
#define usbdevs_h
|
#define usbdevs_h
|
||||||
|
|
||||||
#define USB_VENDOR_ATMEL 1003
|
#define USB_VENDOR_ATMEL 0x03EB
|
||||||
#define USB_DEVICE_JTAGICEMKII 0x2103
|
#define USB_VENDOR_MICROCHIP 0x04D8
|
||||||
#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_FTDI 0x0403
|
#define USB_DEVICE_JTAGICEMKII 0x2103
|
||||||
#define USB_DEVICE_FT2232 0x6010
|
#define USB_DEVICE_AVRISPMKII 0x2104
|
||||||
#define USB_DEVICE_FT245 0x6001
|
#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_VID 0x16C0 /* VOTI */
|
||||||
#define USBASP_SHARED_PID 0x05DC /* Obdev's free shared PID */
|
#define USBASP_SHARED_PID 0x05DC /* Obdev's free shared PID */
|
||||||
|
|
Loading…
Reference in New Issue