Merge pull request #2060 from stefanrueger/bus-device

Ignore leading zeros in -P usb:<bus>:<device> numbers and improve `-P` documentation
This commit is contained in:
Stefan Rueger
2025-10-31 19:11:03 +01:00
committed by GitHub
18 changed files with 519 additions and 420 deletions

View File

@@ -41,7 +41,7 @@
.Op Fl i Ar delay
.Op Fl l, \-logfile Ar logfile
.Op Fl n, \-test-memory
.Op Fl O, \-osccal
.Op Fl O, \-osccal
.Op Fl P, \-port Ar port
.Op Fl r, \-reconnect
.Op Fl q, \-quell
@@ -607,6 +607,14 @@ or
from the configuration file are used. If you need to use a different port,
use this option to specify the alternate port name.
.Pp
USB-only programmers normally do not need the port option be specified as
they are automatically identified via their vendor and product IDs from
avrdude.conf or .avrduderc. Only when there are multiple programmers of
the same type plugged into the host computer is the -P option needed, see
below. Some -c programmers, however, ignore the -P option altogether, eg,
teensy, ch341a or avrftdi; these cannot distinguish multiple plugged-in
programmers.
.Pp
If
.Nm
has been configured with libserialport support, a serial port can be specified
@@ -663,20 +671,38 @@ The match is done after stripping any existing colons from the given
serial number, and right-to-left, so only the least significant bytes
from the serial number need to be given.
.Pp
avrdude -v -P usb:xyz -c jtag2 -p ... 2>&1 | grep ^Found
.Pp
lists all JTAG ICEs
attached to USB, see the section
.Em Example Command Line Invocations
in the detailed pdf documentation.
.Pp
As the AVRISP mkII device can only be talked to over USB, the very
same method of specifying the port is required there.
.Pp
For the USB programmer "AVR-Doper" running in HID mode, the port must
For the USB programmer AVR-Doper running in HID mode, the port must
be specified as
.Ar avrdoper.
Libhidapi support is required on Unix and Mac OS but not on Windows. For more
information about AVR-Doper see https://www.obdev.at/products/vusb/avrdoper.html.
.Pp
For the USBtinyISP, which is a simplistic device not implementing
serial numbers, multiple devices can be distinguished by their
location in the USB hierarchy. See the respective
For the USBtinyISP, which is a simplistic device not implementing serial
numbers, multiple devices can be distinguished by their location in the
USB hierarchy using -P usb:<busdir>:<devicefile>.
.Pp
For USBasp, multiple devices can also be also distinguished using -P
usb:<busdir>:<devicefile> or using the serial number -P usb:<serialno>.
For examples, see the respective
.Em Troubleshooting
entry in the detailed documentation for examples.
entry in the detailed pdf documentation.
.Pp
The -c pickit5 programmer allows overriding the product ID with a
hexadecimal number <pid> using -P usb::<pid> and the vendor and product
IDs with hexadecimal numbers <vid> and <pid> using -P usb:<vid>:<pid>. The
form -P usb:<serialno> requests AVRDUDE select the PICkit5 programmer with
a serial number that ends in <serialno> (and with vid/pid from the
configuration files).
.Pp
For the XBee programmer the target MCU is to be programmed wirelessly over a
ZigBee mesh using the XBeeBoot bootloader. The ZigBee 64-bit address for the
@@ -968,10 +994,13 @@ The
.Ar addr
and
.Ar len
parameters of the dump, read, disasm, write, save and erase commands can be
negative with the same syntax as substring computations in perl or python.
The table below details their meaning with respect to an example memory of size
sz=0x800 (2048 bytes).
parameters of the dump, read, disasm, write, save and erase commands can
be negative with the same syntax as substring computations in perl or
python. The table below defines the effective memory interval
.Ar [start ,
.Ar end],
given the memory size
.Ar sz :
.Pp
.nf
addr len Memory interval Comment
@@ -982,6 +1011,19 @@ addr len Memory interval Comment
sz+addr+len-1]
neg neg [sz+addr, sz+len] Combining above two cases
any 0 empty set No action
.fi
.Pp
Note that addr must be in the range [-sz, sz-1]. After computing the memory interval
[start, end] as per above table, the effective length end-start + 1 must not be negative; if
the effective length is zero then no action is carried out. End may be beyond the available
memory for the dump, read or disasm commands, in which case the operation wraps around
the memory end, but the effective length is always limited to the memory size.
.Pp
Here some examples for a memory with size sz of 0x800 (2048) bytes:
.Pp
.nf
addr len Memory interval Comment
------------------------------------------------------------------------
0x700 12 [0x700, 0x70b] Conventional use
1024 -257 [0x400, 0x6ff] Size of memory is 2048 or 0x800
-512 512 [0x600, 0x7ff] Last 512 bytes
@@ -989,6 +1031,11 @@ addr len Memory interval Comment
0 49 [0, 48] First 49 bytes
0 -49 [0, 1999] All but the last 48 = |len+1| bytes
0 -1 [0, 0x7ff] All memory without knowing its size
2046 4 [0x7fe, 0x801] Wrap around for read but error for write
2046 4096 [0x7fe, 0x17fe] Read wrap around stops at 0x7fd
-1 -1 [0x7ff, 0x7ff] One byte at 0x7ff is addressed
-1 -2 [0x7ff, 0x7fe] No action: effective length is zero
-1 -3 [0x7ff, 0x7fd] Error: effective length is negative
.fi
.Pp
The following commands are implemented for all programmers:
@@ -1639,7 +1686,7 @@ to the target. If there is already a valid voltage applied to the VTG Pin,
this setting will be ignored. When AVRDUDE detects an external voltage outside
of this range, it will terminate the operation. You can disable this check by
setting the voltage to 0 V. If an XMEGA part was selected, a requested voltage
above 3.49 V will lead to an abort of operation.
above 3.49 V will lead to an abort of operation.
.It Ar hvupdi
High-voltage UPDI programming is used to enable a UPDI pin that has previously
been set to RESET or GPIO mode. Use -x hvupdi to enable high-voltage UPDI

View File

@@ -641,6 +641,10 @@ static int avrftdi_open(PROGRAMMER *pgm, const char *port) {
Avrftdi_data *pdata = to_pdata(pgm);
pmsg_debug("%s(\"%s\")\n", __func__, port);
if(!str_eq(port, "usb"))
pmsg_warning("option -P %s ignored\n", port);
// Parameter validation
// Use vid/pid in following priority: config, defaults cmd-line is currently not supported

View File

@@ -201,7 +201,9 @@ static int ch341a_open(PROGRAMMER *pgm, const char *port) {
int errorCode = USB_ERROR_NOTFOUND;
libusb_device_handle *handle = NULL;
pmsg_trace("ch341a_open(\"%s\")\n", port);
pmsg_debug("%s(\"%s\")\n", __func__, port);
if(!str_eq(port, "usb"))
pmsg_warning("option -P %s ignored\n", port);
if(!my.USB_init) {
my.USB_init = 1;

View File

@@ -92,25 +92,26 @@ static char *get_usb_string(usb_dev_handle *dev_handle, int index);
struct dfu_dev *dfu_open(const char *port_spec) {
struct dfu_dev *dfu;
char *bus_name = NULL;
char *dev_name = NULL;
char *bus_name = NULL, *dev_name = NULL;
/* The following USB device spec parsing code was copied from usbtiny.c. The
* expected format is "usb:BUS:DEV" where BUS and DEV are the bus and device
* names. We stash these away in the dfu_dev structure for the dfu_init()
* function, where we actually open the device.
/*
* The following USB device spec parsing code was copied from usbtiny.c.
* The expected format is "usb:<busdir>:<devicefile>". We stash these
* away in the dfu_dev structure for the dfu_init() function, where we
* actually open the device.
*/
if(!str_starts(port_spec, "usb")) {
pmsg_error("invalid port specification %s for USB device\n", port_spec);
pmsg_debug("%s(\"%s\")\n", __func__, port_spec);
if(!str_starts(port_spec, "usb:") && !str_eq(port_spec, "usb")) {
pmsg_error("invalid -P %s; drop this option or use -P usb:<busdir>:<devicefile>\n", port_spec);
return NULL;
}
if(':' == port_spec[3]) {
bus_name = mmt_strdup(port_spec + 3 + 1);
dev_name = strchr(bus_name, ':');
if(NULL != dev_name)
if((dev_name = strchr(bus_name, ':')))
*dev_name++ = '\0';
}
@@ -138,17 +139,19 @@ int dfu_init(struct dfu_dev *dfu, unsigned short vid, unsigned short pid) {
struct usb_device *dev;
struct usb_bus *bus;
/* At last, we reach out through the USB bus to the part. There are three
* ways to specify the part: by USB address, by USB vendor and product id,
* and by part name. To specify the part by USB address, the user specifies
* a port parameter in the form "usb:BUS:DEV" (see dfu_open()). To specify
* the part by vendor and product, the user must specify a usbvid and usbpid
* in the configuration file. Finally, if the user specifies the part only,
* we use the default vendor and product id.
/*
* At last, we reach out through the USB bus to the part. There are
* three ways to specify the part: by USB address, by USB vendor and
* product id, and by part name. To specify the part by USB address, the
* user specifies a port parameter in the form usb:<busdir>:<devicefile>
* (see dfu_open()). To specify the part by vendor and product, the user
* must specify a usbvid and usbpid in the configuration file. Finally,
* if the user specifies the part only, we use the default vendor and
* product id.
*/
if(pid == 0 && dfu->dev_name == NULL) {
pmsg_error("no DFU support for part; specify PID in config or USB address (via -P) to override\n");
pmsg_error("no DFU support for part; specify <pid> in config or USB address via -P usb:<busdir>:<devicefile>\n");
return -1;
}
@@ -164,10 +167,14 @@ int dfu_init(struct dfu_dev *dfu, unsigned short vid, unsigned short pid) {
for(bus = usb_busses; !found && bus != NULL; bus = bus->next) {
for(dev = bus->devices; !found && dev != NULL; dev = dev->next) {
if(dfu->bus_name != NULL && !str_eq(bus->dirname, dfu->bus_name))
if(vid == dev->descriptor.idVendor && pid == dev->descriptor.idProduct)
pmsg_notice("found device with vendorID=0x%04x and productID=0x%04x, busdir:devicefile = %s:%s\n",
vid, pid, bus->dirname, dev->filename);
if(dfu->bus_name && !str_busdev_eq(bus->dirname, dfu->bus_name))
continue;
if(dfu->dev_name != NULL) {
if(!str_eq(dev->filename, dfu->dev_name))
if(dfu->dev_name) {
if(!str_busdev_eq(dev->filename, dfu->dev_name))
continue;
} else if(vid != dev->descriptor.idVendor)
continue;
@@ -187,7 +194,7 @@ int dfu_init(struct dfu_dev *dfu, unsigned short vid, unsigned short pid) {
return -1;
}
pmsg_notice2("found VID=0x%04x PID=0x%04x at %s:%s\n",
pmsg_notice2("using VID=0x%04x PID=0x%04x at %s:%s\n",
found->descriptor.idVendor, found->descriptor.idProduct, found->bus->dirname, found->filename);
dfu->dev_handle = usb_open(found);
@@ -223,14 +230,10 @@ int dfu_init(struct dfu_dev *dfu, unsigned short vid, unsigned short pid) {
void dfu_close(struct dfu_dev *dfu) {
if(dfu->dev_handle != NULL)
usb_close(dfu->dev_handle);
if(dfu->bus_name != NULL)
mmt_free(dfu->bus_name);
if(dfu->manf_str != NULL)
mmt_free(dfu->manf_str);
if(dfu->prod_str != NULL)
mmt_free(dfu->prod_str);
if(dfu->serno_str != NULL)
mmt_free(dfu->serno_str);
mmt_free(dfu->bus_name);
mmt_free(dfu->manf_str);
mmt_free(dfu->prod_str);
mmt_free(dfu->serno_str);
}
int dfu_getstatus(struct dfu_dev *dfu, struct dfu_status *status) {

View File

@@ -366,7 +366,7 @@ caters for these urboot bootloaders. Owing to its backward compatibility,
bootloaders that can be served by the arduino programmer can normally also
be served by the urclock programmer. This may require specifying the size
of (to AVRDUDE) @emph{unknown} bootloaders in bytes using the @code{-x
bootsize=<n>} option, which is necessary for the urclock programmer to
bootsize=@var{n}} option, which is necessary for the urclock programmer to
enable it to protect the bootloader from being overwritten. If an unknown
bootloader has EEPROM read/write capability then the option @code{-x eepromrw}
informs @code{avrdude -c urclock} of that capability.
@@ -637,10 +637,10 @@ two locations:
@enumerate
@item
@code{<directory from which application loaded>/../etc/avrdude.conf}
@code{@var{directory from which application loaded}/../etc/avrdude.conf}
@item
@code{<directory from which application loaded>/avrdude.conf}
@code{@var{directory from which application loaded}/avrdude.conf}
@end enumerate
@@ -824,9 +824,17 @@ specification, system-dependent default values @code{default_parallel},
the configuration file are used. If you need to use a different port, use this
option to specify the alternate port name.
USB-only programmers normally do not need the port option be specified as
they are automatically identified via their vendor and product IDs from
@code{avrdude.conf} or @code{.avrduderc}. Only when there are multiple
programmers of the same type plugged into the host computer is the
@code{-P} option needed, see below. Some @code{-c} programmers, however,
ignore the @code{-P} option altogether, eg, teensy, ch341a or avrftdi;
these cannot distinguish multiple plugged-in programmers.
If avrdude has been configured with libserialport support, a serial port
can be specified using a predefined serial adapter type in
@var{avrdude.conf} or @var{.avrduderc}, e.g., @code{ch340} or
@code{avrdude.conf} or @code{.avrduderc}, e.g., @code{ch340} or
@code{ft232r}. If more than one serial adapter of the same type is
connected, they can be distinguished by appending a serial number, e.g.,
@code{ft232r:12345678}. Note that the USB to serial chip has to have a
@@ -842,31 +850,41 @@ list of all possible serial adapters known to avrdude use @code{-P ?sa}.
Depending on the used shell, @code{?} may need to be quoted as in
@code{"?"} or @code{\?}.
For the JTAG ICE mkII, if AVRDUDE has been built with libusb support,
@var{port} may alternatively be specified as
@code{usb}[:@var{serialno}]. In that case, the JTAG ICE mkII will be
looked up on USB. If @var{serialno} is also specified, it will be
matched against the serial number read from any JTAG ICE mkII found on
USB. The match is done after stripping any existing colons from the
given serial number, and right-to-left, so only the least significant
bytes from the serial number need to be given.
For a trick how to find out the serial numbers of all JTAG ICEs
For the JTAG ICE mkII, if AVRDUDE has been built with libusb support, the
port can be specified as @code{usb}[:@var{serialno}]. In that case, the
JTAG ICE mkII will be looked up on USB. If @var{serialno} is also
specified, it will be matched against the serial number read from any JTAG
ICE mkII found on USB. The match is done after stripping any existing
colons from the given serial number, and right-to-left, so only the least
significant bytes from the serial number need to be given.
@code{avrdude -v -P usb:xyz -c jtag2 -p ... 2>&1 | grep ^Found} lists all JTAG ICEs
attached to USB, see @ref{Example Command Line Invocations}.
As the AVRISP mkII device can only be talked to over USB, the very
same method of specifying the port is required there.
For the USB programmer "AVR-Doper" running in HID mode, the port must
be specified as @var{avrdoper}. Libhidapi support is required on Unix
and Mac OS but not on Windows. For more information about AVR-Doper see
For the USB programmer AVR-Doper running in HID mode, the port must be
specified as @code{-P avrdoper}. Libhidapi support is required on Unix and
Mac OS but not on Windows. For more information about AVR-Doper see
@url{https://www.obdev.at/products/vusb/avrdoper.html}.
For the USBtinyISP, which is a simplistic device not implementing
serial numbers, multiple devices can be distinguished by their
location in the USB hierarchy.
For USBasp, multiple devices can be distinguished by either USB connection
or serial number.
See the respective @ref{Troubleshooting} entry for examples.
For the USBtinyISP, which is a simplistic device not implementing serial
numbers, multiple devices can be distinguished by their location in the
USB hierarchy using @code{-P usb:@var{busdir}:@var{devicefile}}.
For USBasp, multiple devices can also be also distinguished using @code{-P
usb:@var{busdir}:@var{devicefile}} or using the serial number @code{-P
usb:@var{serialno}}. The USBasp serial number is matched from the end, so
only the unique least significant bytes are needed. For examples, see the
respective entry in @ref{Troubleshooting}.
The @code{-c pickit5} programmer allows overriding the product ID with a
hexadecimal number @var{pid} using @code{-P usb::@var{pid}} and the vendor
and product IDs with hexadecimal numbers @var{vid} and @var{pid} using
@code{-P usb:@var{vid}:@var{pid}}. The form @code{-P usb:@var{serialno}}
requests AVRDUDE select the PICkit5 programmer with a serial number that
ends in @var{serialno} (and with @var{vid}/@var{pid} from the
configuration files).
For the XBee programmer the target MCU is to be programmed wirelessly
over a ZigBee mesh using the XBeeBoot bootloader. The ZigBee 64-bit
@@ -877,10 +895,9 @@ directly contactable XBee device associated with the same mesh (with
a default baud rate of 9600). This may look similar to:
@code{0013a20000000001@/dev/tty.serial}.
For diagnostic purposes, if the target MCU with an XBeeBoot
bootloader is connected directly to the serial port, the
64-bit address field can be omitted. In this mode the
default baud rate will be 19200.
For diagnostic purposes, if the target MCU with an XBeeBoot bootloader is
connected directly to the serial port, the 64-bit address field can be
omitted. In this mode the default baud rate will be 19200.
For programmers that attach to a serial port using some kind of
higher level protocol (as opposed to bit-bang style programmers),
@@ -898,8 +915,7 @@ The port is assumed to be properly configured, for example using a
transparent 8-bit data connection without parity at 115200 Baud
for a STK500.
Note: The ability to handle IPv6 hostnames and addresses is limited to
Posix systems (by now).
Note: IPv6 hostnames and addresses are limited to Posix systems.
@item -r
@item --reconnect
@@ -1309,8 +1325,8 @@ flash:r:-:I}. Patterns in flash memory are executable and represent benign
AVR code, ie, no I/O memory access. Choose a fixed seed for reproducible
results.
@item init=<n>
Shortcut for @code{-x init -x seed=<n>} (see below)
@item init=@var{n}
Shortcut for @code{-x init -x seed=@var{n}} (see below)
@cindex @code{flash}
@item random
@@ -1319,10 +1335,10 @@ randomly configured with respect to bootloader, data and code length.
Random code in flash will be benign, that is, not accessing I/O memories,
SRAM or flash. Choose a fixed seed for reproducible results.
@item random=<n>
Shortcut for @code{-x random -x seed=<n>}
@item random=@var{n}
Shortcut for @code{-x random -x seed=@var{n}}
@item seed=<n>
@item seed=@var{n}
Seed random number generator with @var{n}; the default is
@code{time(NULL)}. Setting this option with a fixed positive @var{n} will
make the random choices reproducible, ie, they will stay the same between
@@ -1518,7 +1534,7 @@ The generated on-board analog reference voltage for channel 0 or channel 1 can
be changed by specifying a new reference voltage.
The current reference voltage can be read by @code{-x varef0} or
@code{-x varef1} alone.
@item attempts[=<1..99>]
@item attempts[=@var{1..99}]
@var{STK500V1 only}
@*
Specify how many connection retry attempts to perform before exiting.
@@ -1571,7 +1587,7 @@ programmer creates errors during initial sequence.
The Arduino programmer type accepts the following extended parameter:
@table @code
@item attempts[=<1..99>]
@item attempts[=@var{1..99}]
Specify how many connection retry attempts to perform before exiting.
Defaults to 10 if not specified.
@item noautoreset
@@ -1596,10 +1612,10 @@ connected part and bootloader.
@cindex @code{eeprom}
@item showid
Show a unique Urclock ID stored in either flash or EEPROM of the MCU, then exit.
@item id=<E|F>.<addr>.<len>
@item id=@var{E|F}.@var{addr}.@var{len}
Historically, the Urclock ID was a six-byte unique little-endian number
stored in Urclock boards at EEPROM address 257. The location of this
number can be set by the @code{-x id=<E|F>.<addr>.<len>} extended parameter. @code{E}
number can be set by the @code{-x id=@var{E|F}.@var{addr}.@var{len}} extended parameter. @code{E}
stands for EEPROM and @code{F} stands for flash. A negative address addr counts
from the end of EEPROM and flash, respectively. The length len of the
Urclock ID can be between 1 and 8 bytes.
@@ -1613,8 +1629,8 @@ programmer stores by default in high flash just under the bootloader; see also
@code{-x nometadata}.
@item showfilename
Show the input filename (or title) of the last flash writing session, then exit.
@item title=<string>
When set, <string> will be used in lieu of the input filename. The maximum
@item title=@var{string}
When set, @var{string} will be used in lieu of the input filename. The maximum
string length for the title/filename field is 254 bytes including
terminating nul.
@item showapp
@@ -1637,7 +1653,7 @@ just behind the vector table with the name @code{VBL_ADDITIONAL_VECTOR}.
@item showpart
Show the part for which the bootloader was compiled, then exit.
@cindex @code{flash}
@item bootsize=<size>
@item bootsize=@var{size}
Manual override for bootloader size. Urboot bootloaders put the number of
used bootloader pages into a table at the top of the bootloader section,
i.e., typically top of flash, so the urclock programmer can look up the
@@ -1645,7 +1661,7 @@ bootloader size itself. In backward-compatibility mode, when programming
via other bootloaders, this option can be used to tell the programmer the
size, and therefore the location, of the bootloader.
@cindex @code{flash}
@item vectornum=<n>
@item vectornum=@var{n}
Manual override for vector number. Urboot bootloaders put the vector
number used by a vector bootloader into a table at the top of flash, so
this option is normally not needed for urboot bootloaders. However, it is
@@ -1711,9 +1727,9 @@ that a @code{-x showall} query on flash prepared with @code{-x nometadata}
yields useful results.
@item noautoreset
Do not toggle RTS/DTR lines on port open to prevent a hardware reset.
@item delay=<n>
Add a <n> ms delay after reset. This can be useful if a board takes a
particularly long time to exit from external reset. <n> can be negative,
@item delay=@var{n}
Add a @var{n} ms delay after reset. This can be useful if a board takes a
particularly long time to exit from external reset. @var{n} can be negative,
in which case the default 120 ms delay after issuing reset will be
shortened accordingly.
@item strict
@@ -1750,26 +1766,26 @@ aux or aux2). Otherwise the SPI traffic in one active circuit may interfere
with programming the AVR in the other design.
@item spifreq=@var{0..7}
@multitable @columnfractions .05 .3
@item @code{0} @tab 30 kHz (default)
@item @code{1} @tab 125 kHz
@item @code{2} @tab 250 kHz
@item @code{3} @tab 1 MHz
@item @code{4} @tab 2 MHz
@item @code{5} @tab 2.6 MHz
@item @code{6} @tab 4 MHz
@item @code{7} @tab 8 MHz
@multitable @columnfractions 0.05 0.05 0.3
@item @tab @code{0} @tab 30 kHz (default)
@item @tab @code{1} @tab 125 kHz
@item @tab @code{2} @tab 250 kHz
@item @tab @code{3} @tab 1 MHz
@item @tab @code{4} @tab 2 MHz
@item @tab @code{5} @tab 2.6 MHz
@item @tab @code{6} @tab 4 MHz
@item @tab @code{7} @tab 8 MHz
@end multitable
@item rawfreq=0..3
Sets the SPI speed and uses the Bus Pirate's binary ``raw-wire'' mode instead
of the default binary SPI mode:
@multitable @columnfractions .05 .3
@item @code{0} @tab 5 kHz
@item @code{1} @tab 50 kHz
@item @code{2} @tab 100 kHz (Firmware v4.2+ only)
@item @code{3} @tab 400 kHz (v4.2+)
@multitable @columnfractions 0.05 0.05 0.7
@item @tab @code{0} @tab 5 kHz
@item @tab @code{1} @tab 50 kHz
@item @tab @code{2} @tab 100 kHz (Firmware v4.2+ only)
@item @tab @code{3} @tab 400 kHz (v4.2+)
@end multitable
The only advantage of the ``raw-wire'' mode is that different SPI frequencies
@@ -1863,13 +1879,13 @@ device is plugged in.
The Wiring programmer type accepts the following extended parameters:
@table @code
@item snooze=<n>
@item snooze=@var{n}
After performing the port open phase, AVRDUDE will wait/snooze for
@var{snooze} milliseconds before continuing to the protocol sync phase.
No toggling of DTR/RTS is performed if @var{snooze} > 0.
@item delay=<n>
Add a <n> milliseconds delay after reset. This can be useful if a board
takes a particularly long time to exit from external reset. <n> can be
@item delay=@var{n}
Add a @var{n} milliseconds delay after reset. This can be useful if a board
takes a particularly long time to exit from external reset. @var{n} can be
negative, in which case the default 100 ms delay after issuing reset will
be shortened accordingly.
@end table
@@ -1881,14 +1897,14 @@ be shortened accordingly.
@item PICkit2
Connection to the PICkit2 programmer:
@multitable @columnfractions .05 .3
@item @code{(AVR)} @tab @code{(PICkit2)}
@item @code{RST} @tab @code{VPP/MCLR (1) }
@item @code{VDD} @tab @code{VDD Target (2) -- possibly optional if AVR self powered }
@item @code{GND} @tab @code{GND (3) }
@item @code{SDI} @tab @code{PGD (4) }
@item @code{SCLK} @tab @code{PDC (5) }
@item @code{OSI} @tab @code{AUX (6) }
@multitable @columnfractions 0.05 0.15 0.8
@headitem @tab @strong{AVR} @tab @strong{PICkit2}
@item @tab @code{RST} @tab @code{VPP/MCLR (1)}
@item @tab @code{VDD} @tab @code{VDD Target (2)} -- optional if AVR self powered
@item @tab @code{GND} @tab @code{GND (3)}
@item @tab @code{SDI} @tab @code{PGD (4)}
@item @tab @code{SCLK} @tab @code{PDC (5)}
@item @tab @code{SDO} @tab @code{AUX (6)}
@end multitable
The PICkit2 programmer type accepts the following extended parameters:
@@ -1921,7 +1937,7 @@ Only applicable to TPI devices (ATtiny 4/5/9/10/20/40).
The xbee programmer type accepts the following extended parameter:
@table @code
@item xbeeresetpin=@var{1..7}
Select the XBee pin @code{DIO<1..7>} that is connected to the MCU's
Select the XBee pin @code{DIO@var{1..7}} that is connected to the MCU's
@code{/RESET} line. The programmer needs to know which DIO pin to use to
reset into the bootloader. The default (3) is the @code{DIO3} pin
(XBee pin 17), but some commercial products use a different XBee
@@ -2199,16 +2215,16 @@ verbosity level:
@smallexample
@cartouche
$ avrdude -c jtag2 -p m128 -P usb:xxx -v
$ avrdude -c jtag2 -p m128 -P usb:xyz -v
Using port : usb:xxx
Using port : usb:xyz
Using programmer : jtag2fast
Programmer baud rate : 115200
Usbdev_open(): Found JTAG ICE, serno: 00A000001C6B
Usbdev_open(): Found JTAG ICE, serno: 00A000001C3A
Usbdev_open(): Found JTAG ICE, serno: 00A000001C30
Error: did not find any (matching) USB device usb:xxx (03eb:2103)
Error: unable to open port usb:xxx for programmer jtag2fast
Found JTAG ICE with serno: 00A000001C6B
Found JTAG ICE with serno: 00A000001C3A
Found JTAG ICE with serno: 00A000001C30
Error: did not find any (matching) USB device usb:xyz (03eb:2103)
Error: unable to open port usb:xyz for programmer jtag2fast
Avrdude done. Thank you.
@end cartouche
@@ -2254,7 +2270,7 @@ Valid commands:
For more details about a terminal command cmd type cmd -?
Other:
!<line> : run the shell <line> in a subshell, eg, !ls *.hex
!@var{line} : run the shell @var{line} in a subshell, eg, !ls *.hex
# ... : ignore rest of line (eg, used as comments in scripts)
Note that not all programmer derivatives support all commands. Flash and
@@ -2552,64 +2568,64 @@ recalled and edited.
The @var{addr} and @var{len} parameters of the dump, read, disasm, write,
save and erase commands can be negative with the same syntax as substring
computations in perl or python. The table below details their meaning with
respect to an example memory of size @code{sz=0x800} (2048 bytes).
computations in perl or python. The table below defines the effective
memory interval [@var{start}, @var{end}], given the memory size @var{sz}:
@multitable {0/negativ}{negativ}{@code{[addr, addr+len-1]}}{End is @code{|len|} bytes below memory size @code{sz}}
@headitem @code{addr}
@tab @code{len}
@multitable {0/positive}{negative}{[@var{sz}+@var{addr}, @var{sz}+@var{addr}+@var{len}-1]}{End is |@var{len}| bytes below mem size @var{sz}}
@headitem @code{@var{addr}}
@tab @code{@var{len}}
@tab Memory interval
@tab Comment
@item 0/positive
@tab positive
@tab @code{[addr, addr+len-1]}
@tab Note: @code{len = end-start + 1}
@tab [@var{addr}, @var{addr}+@var{len}-1]
@tab Note: @var{len} = @var{end}-@var{start} + 1
@item 0/positive
@tab negative
@tab @code{[addr, sz+len]}
@tab End is @code{|len|} bytes below memory size @code{sz}
@tab [@var{addr}, @var{sz}+@var{len}]
@tab End is |@var{len}| bytes below mem size @var{sz}
@item negative
@tab positive
@tab @code{[sz+addr, @dots{}]}
@tab Start is @code{|addr|} bytes below memory size
@tab [@var{sz}+@var{addr}, @var{sz}+@var{addr}+@var{len}-1]
@tab Start is |@var{addr}| bytes below mem size
@item negative
@tab negative
@tab @code{[sz+addr, sz+len]}
@tab [@var{sz}+@var{addr}, @var{sz}+@var{len}]
@tab Combining above two cases
@item any
@tab zero
@tab empty set
@tab No action
@item @verb{|0x700|}
@tab @verb{| 12|}
@tab @code{[0x700, 0x70b]}
@tab Conventional use
@item @verb{| 1024|}
@tab @verb{| -257|}
@tab @code{[0x400, 0x6ff]}
@tab Size of memory is @code{2048} or @code{0x800}
@item @verb{| -512|}
@tab @verb{| 512|}
@tab @code{[0x600, 0x7ff]}
@tab Last 512 bytes
@item @verb{| -256|}
@tab @verb{| -1|}
@tab @code{[0x700, 0x7ff]}
@tab Last 256 bytes
@item @verb{| 0|}
@tab @verb{| 49|}
@tab @code{[0, 48]}
@tab First 49 bytes
@item @verb{| 0|}
@tab @verb{| -49|}
@tab @code{[0, 1999]}
@tab All but the last @code{48 = |len+1|} bytes
@item @verb{| 0|}
@tab @verb{| -1|}
@tab @code{[0, 0x7ff]}
@tab All memory without knowing its size
@end multitable
@noindent
Note that @var{addr} must be in the range [-@var{sz}, @var{sz}-1]. After
computing the memory interval [@var{start}, @var{end}] as per above table,
the @emph{effective} length @var{end}-@var{start} + 1 must not be
negative; if the effective length is zero then no action is carried out.
@var{end} may be beyond the available memory for the dump, read or disasm
commands, in which case the operation wraps around the memory end, but the
effective length is always limited to the memory size.
Here some examples for a memory with size @var{sz} of 0x800 (2048) bytes:
@multitable {0/positive}{negative}{Memory interval}{Wrap around for read but error for write}
@headitem @code{@var{addr}} @tab @code{@var{len}} @tab Memory interval @tab Comment
@item 0x700 @tab 12 @tab [0x700, 0x70b] @tab Conventional use
@item 1024 @tab -257 @tab [0x400, 0x6ff] @tab 0x6ff = 2048-257
@item -512 @tab 512 @tab [0x600, 0x7ff] @tab Last 512 bytes
@item -256 @tab -1 @tab [0x700, 0x7ff] @tab Last 256 bytes
@item 0 @tab 49 @tab [0, 48] @tab First 49 bytes
@item 0 @tab -49 @tab [0, 1999] @tab All but the last 48 = |@var{len}+1| bytes
@item 0 @tab -1 @tab [0, 0x7ff] @tab All memory without knowing its size
@item 2046 @tab 4 @tab [0x7fe, 0x801] @tab Wrap around for read but error for write
@item 2046 @tab 4096 @tab [0x7fe, 0x17fe] @tab Read wrap around stops at 0x7fd
@item -1 @tab -1 @tab [0x7ff, 0x7ff] @tab One byte at 0x7ff is addressed
@item -1 @tab -2 @tab [0x7ff, 0x7fe] @tab No action: effective length is zero
@item -1 @tab -3 @tab [0x7ff, 0x7fd] @tab Error: effective length is negative
@end multitable
@page
@noindent
The following commands are implemented for all programmers:
@@ -2793,62 +2809,62 @@ access, depending on the programmer, might also have flash and EEPROM
directly accessed without cache.
Items @var{data} can have the following formats:
@multitable @columnfractions .32 .42 .20
@item @strong{Type}
@multitable { }{Hexadecimal integer}{@code{C:/My\ projects/blink.hex}}{1, 2, 4 or 8}
@headitem @tab @strong{Type}
@tab @strong{Example}
@tab @strong{Size (bytes)}
@c
@item String
@item @tab String
@tab @code{"Hello, world\n"}
@tab varying
@c
@item File
@item @tab File
@tab @code{C:/My\ projects/blink.hex}
@tab varying
@c
@item File with format
@item @tab File with format
@tab @code{blink.hex:i}
@tab varying
@c
@item Character
@item @tab Character
@tab @code{'A'}
@tab 1
@c
@item Binary integer
@item @tab Binary integer
@tab @code{0b101010}
@tab 1, 2, 4, or 8
@tab 1, 2, 4 or 8
@c
@item Octal integer
@item @tab Octal integer
@tab @code{012345}
@tab 1, 2, 4, or 8
@tab 1, 2, 4 or 8
@c
@item Decimal integer
@item @tab Decimal integer
@tab @code{12345}
@tab 1, 2, 4, or 8
@tab 1, 2, 4 or 8
@c
@item Hexadecimal integer
@item @tab Hexadecimal integer
@tab @code{0x12345}
@tab 1, 2, 4, or 8
@tab 1, 2, 4 or 8
@c
@item Decimal float
@item @tab Decimal float
@tab @code{3.1415926}
@tab 4
@c
@item Hexadecimal float
@item @tab Hexadecimal float
@tab @code{0xA.8p2}
@tab 4
@c
@item Decimal double
@item @tab Decimal double
@tab @code{3.141592653589793D}
@tab 8
@c
@item Hexadecimal double
@item @tab Hexadecimal double
@tab @code{0xA.8p2D}
@tab 8
@c
@end multitable
@var{data}
@var{Data}
can be binary, octal, decimal or hexadecimal integers, floating point
numbers or C-style strings and characters. If nothing matches, @code{data}
will be interpreted as a name of a file containing data, which will be
@@ -2868,14 +2884,14 @@ work (in contrast to @code{-U} operations).
For integers, an optional case-insensitive suffix specifies the data size:
@multitable {@code{H} or @code{S}}{8 bytes (64 bits) }
@item @code{LL}
@multitable { }{@code{H} or @code{S}}{8 bytes (64 bits) }
@item @tab @code{LL}
@tab 8 bytes (64 bits)
@item @code{L}
@item @tab @code{L}
@tab 4 bytes (32 bits)
@item @code{H} or @code{S}
@item @tab @code{H} or @code{S}
@tab 2 bytes (16 bits)
@item @code{HH}
@item @tab @code{HH}
@tab 1 byte (8 bits)
@end multitable
@@ -3122,11 +3138,11 @@ Display the device signature bytes.
@cindex Programming mode
@cindex Variants of parts
Display the current part information, including supported programming modes,
memory and variants tables. Use @var{-m} to only print the memory table,
and @var{-v} to only print the variants table.
memory and variants tables. Use @code{-m} to only print the memory table,
and @code{-v} to only print the variants table.
@item verbose @var{]level]}
@cindex @code{verbose} @var{]level]}
@item verbose @var{[level]}
@cindex @code{verbose} @var{[level]}
Change (when @var{level} is provided), or display the verbosity
level.
The initial verbosity level is controlled by the number of @code{-v} options
@@ -3691,7 +3707,7 @@ Assign the default programmer id. Can be overridden using the @option{-c}
option.
@item default_baudrate = "@var{default-baudrate}";
Assign the default baudrate value that will be used if the programmer doesn't
Assign the default baudrate value that will be used if the programmer does not
provide its specific @code{baudrate} entry. Can be overridden using the @option{-b}
option.
@@ -4905,17 +4921,17 @@ support parallel port programming under macOS.
The following table lists the default names for a given system.
@multitable @columnfractions .30 .30 .30
@item @strong{System}
@multitable @columnfractions 0.05 .15 .30 .30
@item @tab @strong{System}
@tab @strong{Default Parallel Port}
@tab @strong{Default Serial Port}
@item FreeBSD
@item @tab FreeBSD
@tab @code{/dev/ppi0}
@tab @code{/dev/cuad0}
@item Linux
@item @tab Linux
@tab @code{/dev/parport0}
@tab @code{/dev/ttyS0}
@item Solaris
@item @tab Solaris
@tab @code{/dev/printers/0}
@tab @code{/dev/term/a}
@end multitable
@@ -5264,9 +5280,7 @@ Solution: This problem seems to appear with certain versions of Cygwin. Specifyi
@item
Problem: I'm using Linux and my AVR910 programmer is really slow.
Solution (short): @code{setserial @var{port} low_latency}
Solution (long):
Solution:
There are two problems here. First, the system may wait some time before it
passes data from the serial port to the program. Under Linux the following
command works around this (you may need root privileges for this).
@@ -5276,7 +5290,8 @@ command works around this (you may need root privileges for this).
Secondly, the serial interface chip may delay the interrupt for some time.
This behaviour can be changed by setting the FIFO-threshold to one. Under Linux this
can only be done by changing the kernel source in @code{drivers/char/serial.c}.
Search the file for @code{UART_FCR_TRIGGER_8} and replace it with @code{UART_FCR_TRIGGER_1}. Note that overall performance might suffer if there
Search the file for @code{UART_FCR_TRIGGER_8} and replace it with @code{UART_FCR_TRIGGER_1}.
Note that overall performance might suffer if there
is high throughput on serial lines. Also note that you are modifying the kernel at
your own risk.
@@ -5284,33 +5299,32 @@ your own risk.
@item
Problem: I'm not using Linux and my AVR910 programmer is really slow.
Solutions: The reasons for this are the same as above.
Solution: The reasons for this are the same as above.
If you know how to work around this on your OS, please let us know.
@cindex @code{eeprom}
@item
Problem: Page-mode programming the EEPROM (using the -U option) does
Problem: Page-mode programming the EEPROM using the -U option does
not erase EEPROM cells before writing, and thus cannot necessarily overwrite
previous values that are different to 0xff.
non-0xff values.
Solution: None. This is an inherent feature of the way JTAG EEPROM
programming works, and is documented that way in the Atmel AVR
datasheets.
In order to successfully program the EEPROM that way, a prior chip
erase (with the EESAVE fuse unprogrammed) is required.
This also applies to the STK500 and STK600 in high-voltage programming mode.
Solution: This is an inherent feature of how JTAG EEPROM programming
works, and is documented as such in the datasheets. In order to
successfully program the EEPROM, a prior chip erase with the EESAVE fuse
unprogrammed is required. This also applies to the STK500 and STK600 in
high-voltage programming mode.
Programming the EEPROM in the terminal, however, will recognise that the
programmer struggles to write to EEPROM and read the flash, EEPROM and, if
present, bootrow contents, perform a chip erase and then write the
memories back. This happens when flushing the cache or leaving the
terminal and, out of necessity, take some time.
The terminal, however, recognises that the programmer struggles to write
to EEPROM. It then reads flash, EEPROM and, if present, bootrow contents,
performs a chip erase and then writes these memories back. This happens
when flushing the cache or leaving the terminal and takes some time.
EESAVE needs to be unprogrammed for this.
@item
Problem: How do I turn off the @var{DWEN} fuse?
Problem: How do I turn off the @code{DWEN} fuse?
Solution: If the @var{DWEN} (debugWIRE enable) fuse is activated,
the @var{/RESET} pin is not functional anymore, so normal ISP
Solution: If the @code{DWEN} (debugWIRE enable) fuse is activated,
the @code{/RESET} pin is not functional anymore, so normal ISP
communication cannot be established.
There are two options to deactivate that fuse again: high-voltage
programming, or getting the JTAG ICE mkII talk debugWIRE, and
@@ -5319,9 +5333,9 @@ prepare the target AVR to accept normal ISP communication again.
The first option requires a programmer that is capable of high-voltage
programming (either serial or parallel, depending on the AVR device),
for example the STK500. In high-voltage programming mode, the
@var{/RESET} pin is activated initially using a 12 V pulse (thus the
@code{/RESET} pin is activated initially using a 12 V pulse (thus the
name @emph{high voltage}), so the target AVR can subsequently be
reprogrammed, and the @var{DWEN} fuse can be cleared. Typically, this
reprogrammed, and the @code{DWEN} fuse can be cleared. Typically, this
operation cannot be performed while the AVR is located in the target
circuit though.
@@ -5329,58 +5343,61 @@ The second option requires a JTAG ICE mkII that can talk the debugWIRE
protocol. The ICE needs to be connected to the target using the
JTAG-to-ISP adapter, so the JTAG ICE mkII can be used as a debugWIRE
initiator as well as an ISP programmer. AVRDUDE will then be activated
using the @var{jtag2isp} programmer type. The initial ISP
using the @code{jtag2isp} programmer type. The initial ISP
communication attempt will fail, but AVRDUDE then tries to initiate a
debugWIRE reset. When successful, this will leave the target AVR in a
state where it can accept standard ISP communication. The ICE is then
signed off (which will make it signing off from the USB as well), so
AVRDUDE has to be called again afterwards. This time, standard ISP
communication can work, so the @var{DWEN} fuse can be cleared.
communication can work, so the @code{DWEN} fuse can be cleared.
The pin mapping for the JTAG-to-ISP adapter is:
@multitable @columnfractions .2 .2
@item @strong{JTAG pin} @tab @strong{ISP pin}
@item 1 @tab 3
@item 2 @tab 6
@item 3 @tab 1
@item 4 @tab 2
@item 6 @tab 5
@item 9 @tab 4
@multitable @columnfractions 0.1 .1 .1
@item @tab @strong{JTAG} @tab @strong{ISP}
@item @tab 1 @tab 3
@item @tab 2 @tab 6
@item @tab 3 @tab 1
@item @tab 4 @tab 2
@item @tab 6 @tab 5
@item @tab 9 @tab 4
@end multitable
@item
Problem: Multiple USBasp or USBtinyISP programmers connected simultaneously are not
found.
Problem: Differentiate multiple USBtinyISP (or USBasp) programmers
Solution: The USBtinyISP code supports distinguishing multiple
programmers based on their bus:device connection tuple that describes
their place in the USB hierarchy on a specific host. This tuple can
be added to the @var{-P usb} option, similar to adding a serial number
on other USB-based programmers.
The actual naming convention for the bus and device names is
operating-system dependent; AVRDUDE will print out what it found
on the bus when running it with (at least) one @var{-v} option.
By specifying a string that cannot match any existing device
(for example, @var{-P usb:xxx}), the scan will list all possible
candidate devices found on the bus.
Examples:
@example
avrdude -c usbtiny -p atmega8 -P usb:003:025 (Linux)
avrdude -c usbtiny -p atmega8 -P usb:/dev/usb:/dev/ugen1.3 (FreeBSD 8+)
avrdude -c usbtiny -p atmega8 \
-P usb:bus-0:\\.\libusb0-0001--0x1781-0x0c9f (Windows)
@end example
For USBasp, the same format for @var{-P usb} can be used to match usb bus/device. Alternatively,
device serial number can be specified as follows (for serial number '1234').
Solution: The @code{-c usbtiny} programmer distinguishes multiple physical
USBtinyISP devices based on their busdir:devicefile pairs that describe
their place in the USB hierarchy on a specific host. This pair can be
specified in the @code{-P usb:@var{busdir}:@var{devicefile}} option. The
naming convention for the bus and device depends on the operating system.
Examples for Linux, FreeBSD and Windows, respectively:
@example
avrdude -c USBasp -p atmega8 -P usb:1234
$ avrdude -c usbtiny -p atmega8 -P usb:003:025
$ avrdude -c usbtiny -p atmega8 -P usb:/dev/usb:/dev/ugen1.3
$ avrdude -c usbtiny -p atmega8 \
-P 'usb:bus-0:\\?\usb#vid_16c0&pid_05dc#0001#@{a5...ed@}--WinUSB'
@end example
The Windows device name contains the backslash file separator, so the
@code{-P} option will need appropriate quoting on the command line, eg,
in bash with single quotes.
For USBasp the same @code{-P usb:@var{busdir}:@var{devicefile}} as with
USBtiny selects the right device. Alternatively, USBasp can select the
device via its serial number using @code{-P usb:@var{serialno}}.
Note that @code{avrdude -v -P usb:xyz} will print out suitable programmers
on the bus assuming xyz does not match any device.
@noindent
@example
$ avrdude -v -Pusb:xyz -c usbasp -p m328p 2>&1 | grep ^Found
Found USBasp with busdir:devicefile = 001:008, serial_number = 0001
Found USBasp with busdir:devicefile = 001:009, serial_number = 1234
$ avrdude -qq -c USBasp -p atmega8 -P usb:34
@end example
@item
Problem: I cannot do @dots{} when the target is in debugWIRE mode.
@@ -5389,8 +5406,8 @@ Solution: debugWIRE mode imposes several limitations.
The debugWIRE protocol is Atmel's proprietary one-wire (plus ground)
protocol to allow an in-circuit emulation of the smaller AVR devices,
using the @var{/RESET} line.
DebugWIRE mode is initiated by activating the @var{DWEN}
using the @code{/RESET} line.
DebugWIRE mode is initiated by activating the @code{DWEN}
fuse, and then power-cycling the target.
While this mode is mainly intended for debugging/emulation, it
also offers limited programming capabilities.
@@ -5419,19 +5436,19 @@ with the kit, yet I don't have it.
Solution: Use the following pin mapping:
@multitable @columnfractions .2 .2 .2 .2
@item @strong{JTAGICE} @tab @strong{Target} @tab @strong{Squid cab-} @tab @strong{PDI}
@item @strong{mkII probe} @tab @strong{pins} @tab @strong{le colors} @tab @strong{header}
@item 1 (TCK) @tab @tab Black @tab
@item 2 (GND) @tab GND @tab White @tab 6
@item 3 (TDO) @tab @tab Grey @tab
@item 4 (VTref) @tab VTref @tab Purple @tab 2
@item 5 (TMS) @tab @tab Blue @tab
@item 6 (nSRST) @tab PDI_CLK @tab Green @tab 5
@item 7 (N.C.) @tab @tab Yellow @tab
@item 8 (nTRST) @tab @tab Orange @tab
@item 9 (TDI) @tab PDI_DATA @tab Red @tab 1
@item 10 (GND) @tab @tab Brown @tab
@multitable @columnfractions 0.05 0.2 0.2 0.2 0.2
@item @tab @strong{JTAG ICE} @tab @strong{Target} @tab @strong{Squid cable} @tab @strong{PDI}
@item @tab @strong{mkII probe} @tab @strong{pins} @tab @strong{colors} @tab @strong{header}
@item @tab 1 (TCK) @tab @tab Black @tab
@item @tab 2 (GND) @tab GND @tab White @tab 6
@item @tab 3 (TDO) @tab @tab Grey @tab
@item @tab 4 (VTref) @tab VTref @tab Purple @tab 2
@item @tab 5 (TMS) @tab @tab Blue @tab
@item @tab 6 (nSRST) @tab PDI_CLK @tab Green @tab 5
@item @tab 7 (N.C.) @tab @tab Yellow @tab
@item @tab 8 (nTRST) @tab @tab Orange @tab
@item @tab 9 (TDI) @tab PDI_DATA @tab Red @tab 1
@item @tab 10 (GND) @tab @tab Brown @tab
@end multitable
@item
@@ -5440,15 +5457,15 @@ Xmega device through PDI.
Solution: Use the 6 pin ISP header on the Dragon and the following pin mapping:
@multitable @columnfractions .2 .2
@item @strong{Dragon} @tab @strong{Target}
@item @strong{ISP Header} @tab @strong{pins}
@item 1 (SDI) @tab PDI_DATA
@item 2 (VCC) @tab VCC
@item 3 (SCK) @tab
@item 4 (SDO) @tab
@item 5 (RESET) @tab PDI_CLK / RST
@item 6 (GND) @tab GND
@multitable @columnfractions 0.05 0.2 0.3
@item @tab @strong{Dragon} @tab @strong{Target}
@item @tab @strong{ISP Header} @tab @strong{pins}
@item @tab 1 (SDI) @tab PDI_DATA
@item @tab 2 (VCC) @tab VCC
@item @tab 3 (SCK) @tab
@item @tab 4 (SDO) @tab
@item @tab 5 (RESET) @tab PDI_CLK / RST
@item @tab 6 (GND) @tab GND
@end multitable
@item
@@ -5457,15 +5474,15 @@ ATtiny4/5/9/10 device through TPI. How to connect the pins?
Solution: Use the following pin mapping:
@multitable @columnfractions .2 .2 .2
@item @strong{AVRISP} @tab @strong{Target} @tab @strong{ATtiny}
@item @strong{connector} @tab @strong{pins} @tab @strong{pin #}
@item 1 (SDI) @tab TPIDATA @tab 1
@item 2 (VTref) @tab Vcc @tab 5
@item 3 (SCK) @tab TPICLK @tab 3
@item 4 (SDO) @tab @tab
@item 5 (RESET) @tab /RESET @tab 6
@item 6 (GND) @tab GND @tab 2
@multitable @columnfractions 0.05 .2 .2 .2
@item @tab @strong{AVRISP} @tab @strong{Target} @tab @strong{ATtiny}
@item @tab @strong{connector} @tab @strong{pins} @tab @strong{pin #}
@item @tab 1 (SDI) @tab TPIDATA @tab 1
@item @tab 2 (VTref) @tab Vcc @tab 5
@item @tab 3 (SCK) @tab TPICLK @tab 3
@item @tab 4 (SDO) @tab @tab
@item @tab 5 (RESET) @tab /RESET @tab 6
@item @tab 6 (GND) @tab GND @tab 2
@end multitable
@item
@@ -5473,13 +5490,13 @@ Problem: I want to program an ATtiny4/5/9/10 device using a serial/parallel
bitbang programmer. How to connect the pins?
Solution: Since TPI has only 1 pin for bi-directional data transfer, both
@var{SDI} and @var{SDO} pins should be connected to the @var{TPIDATA} pin
@code{SDI} and @code{SDO} pins should be connected to the @code{TPIDATA} pin
on the ATtiny device.
However, a 1K resistor should be placed between the @var{SDO} and @var{TPIDATA}.
The @var{SDI} pin connects to @var{TPIDATA} directly.
The @var{SCK} pin is connected to @var{TPICLK}.
However, a 1K resistor should be placed between the @code{SDO} and @code{TPIDATA}.
The @code{SDI} pin connects to @code{TPIDATA} directly.
The @code{SCK} pin is connected to @code{TPICLK}.
In addition, the @var{Vcc}, @var{/RESET} and @var{GND} pins should
In addition, the @code{Vcc}, @code{/RESET} and @code{GND} pins should
be connected to their respective ports on the ATtiny device.
@item
@@ -5487,7 +5504,7 @@ Problem: How can I use a FTDI FT232R USB-to-Serial device for bitbang programmin
Solution: When connecting the FT232 directly to the pins of the target Atmel device,
the polarity of the pins defined in the @code{programmer} definition should be
inverted by prefixing a tilde. For example, the @var{dasa} programmer would
inverted by prefixing a tilde. For example, the @code{dasa} programmer would
look like this when connected via a FT232R device (notice the tildes in
front of pins 7, 4, 3 and 8):
@@ -5514,7 +5531,7 @@ Solution: Mind the limited programming supply voltage range of these
devices.
In-circuit programming through TPI is only guaranteed by the datasheet
at Vcc = 5 V.
at Vcc = 5@w{ }V.
@item
Problem: My ATxmega@dots{}A1/A2/A3 cannot be programmed through PDI with
@@ -5545,7 +5562,7 @@ speed (e.g. through the @code{CLKPR} register), further ISP connection
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 @code{/RESET} low, the
target continues to run at the internal clock speed either as defined by
the firmware running before or as set by the factory. Therefore, the
ISP clock speed must be reduced appropriately (to less than 1/4 of the
@@ -5570,8 +5587,8 @@ erase cycle.
AVRDUDE supports the programmers below: the left column lists the
programmer's id as used for @code{-c}, whilst the right column contains a
short description and the list of available programming interface(s) in
brackets; see @ref{Programmer Definitions}). There is more detail about
short description and the list of available programming interfaces in
brackets; see @ref{Programmer Definitions}. There is more detail about
each programmer in the AVRDUDE configuration file.
@multitable @columnfractions .24 .75

View File

@@ -1701,6 +1701,12 @@ int segment_normalise(const AVRMEM *mem, Segment *segp) {
return -1;
}
if(len > 0 && addr+len-1 >= maxsize) {
pmsg_error("segment length %d with starting address 0x%0*x reaches beyond memory end 0x%0*x\n",
segp->len, digits, addr, digits, maxsize-1);
return -1;
}
segp->addr = addr;
segp->len = len;

View File

@@ -811,6 +811,8 @@ static int ft245r_open(PROGRAMMER *pgm, const char *port) {
int devnum = -1;
char device[9] = "";
pmsg_debug("%s(\"%s\")\n", __func__, port);
rv = pins_check(pgm, pin_checklist, sizeof(pin_checklist)/sizeof(pin_checklist[0]), true);
if(rv) {

View File

@@ -1384,7 +1384,7 @@ static int jtagmkII_parseextparms(const PROGRAMMER *pgm, const LISTID extparms)
static int jtagmkII_open(PROGRAMMER *pgm, const char *port) {
union pinfo pinfo;
pmsg_notice2("jtagmkII_open()\n");
pmsg_notice2("%s(\"%s\")\n", __func__, port);
/*
* The JTAG ICE mkII always starts with a baud rate of 19200 Bd upon
@@ -1434,7 +1434,7 @@ static int jtagmkII_open(PROGRAMMER *pgm, const char *port) {
static int jtagmkII_open_dw(PROGRAMMER *pgm, const char *port) {
union pinfo pinfo;
pmsg_notice2("jtagmkII_open_dw()\n");
pmsg_notice2("%s(\"%s\")\n", __func__, port);
/*
* The JTAG ICE mkII always starts with a baud rate of 19200 Bd upon
@@ -1484,7 +1484,7 @@ static int jtagmkII_open_dw(PROGRAMMER *pgm, const char *port) {
static int jtagmkII_open_pdi(PROGRAMMER *pgm, const char *port) {
union pinfo pinfo;
pmsg_notice2("jtagmkII_open_pdi()\n");
pmsg_notice2("%s(\"%s\")\n", __func__, port);
/*
* The JTAG ICE mkII always starts with a baud rate of 19200 Bd upon
@@ -1540,7 +1540,7 @@ static int jtagmkII_open_pdi(PROGRAMMER *pgm, const char *port) {
static int jtagmkII_dragon_open(PROGRAMMER *pgm, const char *port) {
union pinfo pinfo;
pmsg_notice2("jtagmkII_dragon_open()\n");
pmsg_notice2("%s(\"%s\")\n", __func__, port);
/*
* The JTAG ICE mkII always starts with a baud rate of 19200 Bd upon
@@ -1590,7 +1590,7 @@ static int jtagmkII_dragon_open(PROGRAMMER *pgm, const char *port) {
static int jtagmkII_dragon_open_dw(PROGRAMMER *pgm, const char *port) {
union pinfo pinfo;
pmsg_notice2("jtagmkII_dragon_open_dw()\n");
pmsg_notice2("%s(\"%s\")\n", __func__, port);
/*
* The JTAG ICE mkII always starts with a baud rate of 19200 Bd upon
@@ -1640,7 +1640,7 @@ static int jtagmkII_dragon_open_dw(PROGRAMMER *pgm, const char *port) {
static int jtagmkII_dragon_open_pdi(PROGRAMMER *pgm, const char *port) {
union pinfo pinfo;
pmsg_notice2("jtagmkII_dragon_open_pdi()\n");
pmsg_notice2("%s(\"%s\")\n", __func__, port);
/*
* The JTAG ICE mkII always starts with a baud rate of 19200 Bd upon
@@ -3222,7 +3222,7 @@ static int jtagmkII_open32(PROGRAMMER *pgm, const char *port) {
unsigned char buf[6], *resp;
union pinfo pinfo;
pmsg_notice2("jtagmkII_open32()\n");
pmsg_notice2("%s(\"%s\")\n", __func__, port);
/*
* The JTAG ICE mkII always starts with a baud rate of 19200 Bd upon

View File

@@ -1680,6 +1680,7 @@ extern "C" {
int str_casematched_by(const char *string, const char *pattern);
int str_is_pattern(const char *str);
int str_is_in_list(const char *s, const char **l, size_t nl, int (*f)(const char *, const char *));
int str_busdev_eq(const char *s, const char *t);
char *str_sprintf(const char *fmt, ...)
#if defined(__GNUC__) // Ask gcc to check whether format and parameters match
__attribute__((format(printf, 1, 2)))

View File

@@ -577,34 +577,26 @@ static int micronucleus_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) {
}
static int micronucleus_open(PROGRAMMER *pgm, const char *port) {
pmsg_debug("micronucleus_open(\"%s\")\n", port);
pmsg_debug("%s(\"%s\")\n", __func__, port);
if(pgm->bitclock)
pmsg_warning("-c %s does not support adjustable bitclock speed; ignoring -B\n", pgmid);
struct pdata *pdata = &my;
const char *bus_name = NULL;
char *dev_name = NULL;
const char *bus_name = NULL, *dev_name = NULL;
// If no -P was given or '-P usb' was given
if(str_eq(port, "usb")) {
port = NULL;
} else {
// Calculate bus and device names from -P option
if(str_starts(port, "usb") && ':' == port[3]) {
bus_name = port + 4;
dev_name = strchr(bus_name, ':');
if(dev_name != NULL) {
*dev_name = '\0';
dev_name++;
}
}
}
if(port != NULL && dev_name == NULL) {
pmsg_error("invalid -P %s; use -P usb:bus:device\n", port);
if(!str_starts(port, "usb:") && !str_eq(port, "usb")) {
pmsg_error("invalid -P %s; drop this option or use -P usb:<busdir>:<devicefile>\n", port);
return -1;
}
// Calculate bus and device names from -P usb:<busdir>:<devicefile> option if present
if(str_starts(port, "usb:")) {
bus_name = port + 4;
if((dev_name = strchr(bus_name, ':')))
dev_name++;
}
// Determine VID/PID
int vid = pgm->usbvid? pgm->usbvid: MICRONUCLEUS_VID;
int pid = MICRONUCLEUS_PID;
@@ -652,15 +644,13 @@ static int micronucleus_open(PROGRAMMER *pgm, const char *port) {
continue;
}
pmsg_notice("found device with Micronucleus V%d.%d, bus:device: %s:%s\n",
pmsg_notice("found device with Micronucleus V%d.%d, busdir:devicefile = %s:%s\n",
pdata->major_version, pdata->minor_version, bus->dirname, device->filename);
// If -P was given, match device by device name and bus name
if(port != NULL) {
if(dev_name == NULL || !str_eq(bus->dirname, bus_name) || !str_eq(device->filename, dev_name)) {
// If -P usb:<busdir>:<devicefile> was given, skip non-matching busdir:devicefile
if(bus_name && dev_name)
if(!str_busdev_eq(bus->dirname, bus_name) || !str_busdev_eq(device->filename, dev_name))
continue;
}
}
if(pdata->major_version > MICRONUCLEUS_MAX_MAJOR_VERSION) {
pmsg_warning("device with unsupported Micronucleus version V%d.%d\n",
@@ -697,6 +687,11 @@ static int micronucleus_open(PROGRAMMER *pgm, const char *port) {
break;
}
if(bus_name && !dev_name) { // Delayed error message, so found devices are printed with -P usb:xyz
pmsg_error("invalid -P %s; drop -P option or use -P usb:<busdir>:<devicefile>\n", port);
return -1;
}
if(!pdata->usb_handle) {
pmsg_error("cannot find device with Micronucleus bootloader (%04X:%04X)\n", vid, pid);
return -1;

View File

@@ -172,6 +172,10 @@ static int pickit2_open(PROGRAMMER *pgm, const char *port) {
if((pgm->ispdelay > 0 || pgm->bitclock > 0) && !(pgm->extra_features & HAS_BITCLOCK_ADJ))
pmsg_warning("setting bitclock despite HAS_BITCLOCK_ADJ missing in pgm->extra_features\n");
pmsg_debug("%s(\"%s\")\n", __func__, port);
if(!str_eq(port, "usb"))
pmsg_warning("option -P %s ignored\n", port);
#ifdef WIN32
my.usb_handle = open_hid(PICKIT2_VID, PICKIT2_PID);

View File

@@ -634,23 +634,24 @@ static int pickit5_upload_data(const PROGRAMMER *pgm, const AVRPART *p, const un
static int pickit5_open(PROGRAMMER *pgm, const char *port) {
if(!pgm->cookie) // Sanity
return -1;
return LIBAVRDUDE_GENERAL_FAILURE;
pmsg_debug("%s(\"%s\")\n", __func__, port);
union pinfo pinfo;
LNODEID usbpid;
int rv = -1;
int rv = LIBAVRDUDE_GENERAL_FAILURE;
size_t serial_num_len = 0;
#if !defined(HAVE_LIBUSB)
pmsg_error("need to be compiled with USB or HIDAPI support\n");
return -1;
return LIBAVRDUDE_GENERAL_FAILURE;
#endif
if(!str_starts(port, "usb")) {
pmsg_error("port names must start with usb\n");
return -1;
if(!str_starts(port, "usb:") && !str_eq(port, "usb")) {
pmsg_error("invalid -P %s; drop -P option or else use -P usb:<vid>:<pid> or -P usb:<serialno>\n", port);
return LIBAVRDUDE_GENERAL_FAILURE;
}
unsigned int new_vid = 0, new_pid = 0;
char *vidp, *pidp;
unsigned int new_vid = 0, new_pid = 0, setids = 0;
const char *vidp, *pidp;
/*
* The syntax for usb devices is defined as:
@@ -674,11 +675,12 @@ static int pickit5_open(PROGRAMMER *pgm, const char *port) {
vidp += 1;
pidp = strchr(vidp, ':');
if(pidp != NULL) {
setids = 1;
if(vidp != pidp) { // User specified an VID
// First: Handle VID input
if(sscanf(vidp, "%x", &new_vid) != 1) {
pmsg_error("failed to parse -P VID input %s: unexpected format\n", vidp);
return -1;
pmsg_error("failed to parse -P VID input %s: expected hexadecimal number\n", vidp);
return LIBAVRDUDE_GENERAL_FAILURE;
}
} else { // VID space empty: default to Microchip
new_vid = USB_VENDOR_MICROCHIP;
@@ -686,16 +688,16 @@ static int pickit5_open(PROGRAMMER *pgm, const char *port) {
// Now handle PID input
if(sscanf(pidp + 1, "%x", &new_pid) != 1) {
pmsg_error("failed to parse -P PID input %s: unexpected format\n", pidp+1);
return -1;
pmsg_error("failed to parse -P PID input %s: expected hexadecimal number\n", pidp+1);
return LIBAVRDUDE_GENERAL_FAILURE;
}
if((new_vid != 0) && (new_pid != 0)) {
pmsg_notice("overwriting VID:PID to %04x:%04x\n", new_vid, new_pid);
port = "usb"; // Overwrite the string to avoid confusing the libusb
}
} // pidp == NULL means vidp could point to serial number
} // vidp == NULL means just 'usb'
pmsg_notice("overwriting VID:PID to %04x:%04x\n", new_vid, new_pid);
port = "usb"; // Overwrite the string to avoid confusing the libusb
} else { // pidp == NULL means vidp points to serial number
serial_num_len = strlen(vidp);
}
} // vidp == NULL means dropped -P option or -P usb
// If the config entry did not specify a USB PID, insert the default one
if(lfirst(pgm->usbpid) == NULL)
@@ -705,7 +707,7 @@ static int pickit5_open(PROGRAMMER *pgm, const char *port) {
// PICkit 5 does not have support for HID, so no need to support it
serdev = &usb_serdev;
if(new_pid != 0 && new_vid != 0) { // In case a specific VID/PID was specified
if(setids) { // In case a specific VID/PID was specified
pinfo.usbinfo.vid = new_vid;
pinfo.usbinfo.pid = new_pid;
pinfo.usbinfo.flags = PINFO_FL_SILENT;
@@ -795,8 +797,13 @@ static int pickit5_open(PROGRAMMER *pgm, const char *port) {
serial_close(&pgm->fd);
return LIBAVRDUDE_EXIT;
}
if(serial_num_len) {
pmsg_error("no device found matching the specified serial number %s", vidp);
return LIBAVRDUDE_GENERAL_FAILURE;
}
pmsg_error("no device found matching VID 0x%04x and PID list: 0x%04x, 0x%04x, 0x%04x\n", USB_VENDOR_MICROCHIP,
USB_DEVICE_PICKIT5, USB_DEVICE_PICKIT4_PIC_MODE, USB_DEVICE_SNAP_PIC_MODE);
USB_DEVICE_PICKIT5, USB_DEVICE_PICKIT4_PIC_MODE, USB_DEVICE_SNAP_PIC_MODE);
imsg_error("nor VID 0x%04x with PID list: 0x%04x, 0x%04x\n", USB_VENDOR_ATMEL, USB_DEVICE_PICKIT4_AVR_MODE, USB_DEVICE_SNAP_AVR_MODE);
return LIBAVRDUDE_EXIT;
}

View File

@@ -241,6 +241,33 @@ int str_is_in_list(const char *s, const char **l, size_t nl, int (*f)(const char
return 0;
}
// Is the string a decimal bus/device number that ends in a colon or nul?
static int is_busdev_num(const char *s) {
const char *t = s;
while(*t >= '0' && *t <= '9')
t++;
return t > s && (*t == ':' || *t == 0);
}
// Do the two strings represent the same decimal number or are they the same up to a limiting colon?
int str_busdev_eq(const char *s, const char *t) {
if(is_busdev_num(s) && is_busdev_num(t))
if(strtoull(s, NULL, 10) == strtoull(t, NULL, 10))
return 1;
int len = 0; // Length of strings up to optional colon
while(s[len] && s[len] != ':' && t[len] && t[len] != ':')
len++;
// Different length means strings are not the same
if((s[len] && s[len] != ':') || (t[len] && t[len] != ':'))
return 0;
return !strncmp(s, t, len);
}
// Return a mmt_malloc'd string with the sprintf() result
char *str_sprintf(const char *fmt, ...) {
int size = 0;

View File

@@ -305,34 +305,15 @@ static int teensy_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) {
}
static int teensy_open(PROGRAMMER *pgm, const char *port) {
pmsg_debug("teensy_open(\"%s\")\n", port);
pmsg_debug("%s(\"%s\")\n", __func__, port);
if(!str_eq(port, "usb"))
pmsg_warning("option -P %s ignored\n", port);
if(pgm->bitclock)
pmsg_warning("-c %s does not support adjustable bitclock speed; ignoring -B\n", pgmid);
struct pdata *pdata = &my;
const char *bus_name = NULL;
char *dev_name = NULL;
// If no -P was given or '-P usb' was given
if(str_eq(port, "usb")) {
port = NULL;
} else {
// Calculate bus and device names from -P option
if(str_starts(port, "usb") && ':' == port[3]) {
bus_name = port + 4;
dev_name = strchr(bus_name, ':');
if(dev_name != NULL) {
*dev_name = '\0';
dev_name++;
}
}
}
if(port != NULL && dev_name == NULL) {
pmsg_error("invalid -P %s; use -P usb:bus:device\n", port);
return -1;
}
// Determine VID/PID
int vid = pgm->usbvid? pgm->usbvid: TEENSY_VID;
int pid = TEENSY_PID;

View File

@@ -2260,6 +2260,8 @@ static int urclock_open(PROGRAMMER *pgm, const char *port) {
pgm->port = port;
pinfo.serialinfo.baud = pgm->baudrate? pgm->baudrate: 115200;
pinfo.serialinfo.cflags = SERIAL_8N1;
pmsg_debug("%s(\"%s\")\n", __func__, port);
if(serial_open(port, pinfo, &pgm->fd) == -1)
return -1;

View File

@@ -142,7 +142,7 @@ static int usbdev_open(const char *port, union pinfo pinfo, union filedescriptor
fd->usb.wep = 0x02;
}
pmsg_notice("%s(): found %s, serno: %s\n", __func__, product, string);
pmsg_notice("found %s with serno = %s\n", product, string);
if(*serno) {
/*
* See if the serial number requested by the user matches what we

View File

@@ -418,22 +418,18 @@ static int usbasp_transmit(const PROGRAMMER *pgm,
return nbytes;
}
static int check_for_port_argument_match(const char *port, char *bus, char *device, char *serial_num) {
static int check_for_port_argument_match(const char *port, const char *bus,
const char *device, const char *serial_num) {
pmsg_debug("%s(): found USBasp, bus:device: %s:%s, serial_number: %s\n", __func__, bus, device, serial_num);
const size_t usb_len = strlen("usb");
pmsg_notice("found USBasp with busdir:devicefile = %s:%s, serial_number = %s\n", bus, device, serial_num);
if(str_starts(port, "usb") && ':' == port[usb_len]) {
port += usb_len + 1;
char *colon_pointer = strchr(port, ':');
if(str_starts(port, "usb:")) {
port += 4;
char *dev_name = strchr(port, ':');
if(dev_name) // Compare with busdir:devicefile
return str_busdev_eq(port, bus) && str_busdev_eq(dev_name+1, device);
if(colon_pointer) {
// Value contains ':' character. Compare with bus/device.
if(strncmp(port, bus, colon_pointer - port))
return 0;
port = colon_pointer + 1;
return str_eq(port, device);
}
// Serial number case
return *port && str_ends(serial_num, port);
}
@@ -481,7 +477,7 @@ static int usbOpenDevice(const PROGRAMMER *pgm, libusb_device_handle **device, i
continue;
}
errorCode = 0;
// Do the names match? if vendorName not given ignore it (any vendor matches)
// Do the names match? If vendorName not given ignore it (any vendor matches)
r = libusb_get_string_descriptor_ascii(handle, descriptor.iManufacturer & 0xff,
(unsigned char *) string, sizeof(string));
if(r < 0) {
@@ -492,7 +488,7 @@ static int usbOpenDevice(const PROGRAMMER *pgm, libusb_device_handle **device, i
}
} else {
pmsg_notice2("seen device from vendor >%s<\n", string);
if((vendorName != NULL) && (vendorName[0] != 0) && !str_eq(string, vendorName))
if(vendorName && vendorName[0] && !str_eq(string, vendorName))
errorCode = USB_ERROR_NOTFOUND;
}
// If productName not given ignore it (any product matches)
@@ -510,16 +506,15 @@ static int usbOpenDevice(const PROGRAMMER *pgm, libusb_device_handle **device, i
errorCode = USB_ERROR_NOTFOUND;
}
if(errorCode == 0) {
if(!str_eq(port, "usb")) {
if(!str_eq(port, DEFAULT_USB)) {
// -P option given
libusb_get_string_descriptor_ascii(handle, descriptor.iSerialNumber,
(unsigned char *) string, sizeof(string));
char bus_num[21];
sprintf(bus_num, "%d", libusb_get_bus_number(dev));
char dev_addr[21];
char bus_num[21], dev_addr[21];
sprintf(bus_num, "%03d", libusb_get_bus_number(dev));
sprintf(dev_addr, "%03d", libusb_get_device_address(dev));
sprintf(dev_addr, "%d", libusb_get_device_address(dev));
if(!check_for_port_argument_match(port, bus_num, dev_addr, string))
errorCode = USB_ERROR_NOTFOUND;
}
@@ -620,11 +615,16 @@ static int usbOpenDevice(const PROGRAMMER *pgm, usb_dev_handle **device, int ven
// Interface prog
static int usbasp_open(PROGRAMMER *pgm, const char *port) {
pmsg_debug("usbasp_open(\"%s\")\n", port);
pmsg_debug("%s(\"%s\")\n", __func__, port);
if(pgm->bitclock && !(pgm->extra_features & HAS_BITCLOCK_ADJ))
pmsg_warning("setting bitclock despite HAS_BITCLOCK_ADJ missing in pgm->extra_features\n");
if(!str_starts(port, "usb:") && !str_eq(port, "usb")) {
pmsg_error("invalid -P %s; drop -P option or else use -P usb:<busdir>:<devicefile> or -P usb:<serialno>\n", port);
return -1;
}
// usb_init will be done in usbOpenDevice
LNODEID usbpid = lfirst(pgm->usbpid);
int pid, vid;
@@ -644,12 +644,11 @@ static int usbasp_open(PROGRAMMER *pgm, const char *port) {
USBASP_OLD_PID, "USBasp", port) == 0) {
cx->usb_access_error = 0;
// Found USBasp with old IDs
pmsg_error("found USB device USBasp with old VID/PID; please update firmware of USBasp\n");
pmsg_error("found USBasp with old VID/PID; please update its firmware\n");
return 0;
}
/*
* original USBasp is specified in config file, so no need to check it
* Original USBasp is specified in config file, so no need to check it
* again here; no alternative found => fall through to generic error
* message
*/

View File

@@ -279,26 +279,24 @@ static int usbtiny_avr_op(const PROGRAMMER *pgm, const AVRPART *p, int op, unsig
// Find a device with the correct VID/PID match for USBtiny
static int usbtiny_open(PROGRAMMER *pgm, const char *name) {
static int usbtiny_open(PROGRAMMER *pgm, const char *port) {
struct usb_bus *bus;
struct usb_device *dev = 0;
const char *bus_name = NULL;
char *dev_name = NULL;
const char *bus_name = NULL, *dev_name = NULL;
int vid, pid;
// If no -P was given or '-P usb' was given
if(str_eq(name, "usb"))
name = NULL;
else {
// Calculate bus and device names from -P option
const size_t usb_len = strlen("usb");
pmsg_debug("%s(\"%s\")\n", __func__, port);
if(str_starts(name, "usb") && ':' == name[usb_len]) {
bus_name = name + usb_len + 1;
dev_name = strchr(bus_name, ':');
if(NULL != dev_name)
*dev_name++ = '\0';
}
if(!str_starts(port, "usb:") && !str_eq(port, "usb")) {
pmsg_error("invalid -P %s; drop this option or use -P usb:<busdir>:<devicefile>\n", port);
return -1;
}
// Calculate bus and device names from -P usb:<busdir>:<devicefile> option if present
if(str_starts(port, "usb:")) {
bus_name = port + 4;
if((dev_name = strchr(bus_name, ':')))
dev_name++;
}
usb_init(); // Initialize the libusb system
@@ -322,14 +320,17 @@ static int usbtiny_open(PROGRAMMER *pgm, const char *name) {
pid = USBTINY_PRODUCT_DEFAULT;
}
// Now we iterate through all the buses and devices
// Iterate through all the buses and devices
for(bus = usb_busses; bus; bus = bus->next) {
for(dev = bus->devices; dev; dev = dev->next) {
if(dev->descriptor.idVendor == vid && dev->descriptor.idProduct == pid) { // Found match?
pmsg_debug("%s(): found USBtinyISP, bus:device: %s:%s\n", __func__, bus->dirname, dev->filename);
// If -P was given, match device by device name and bus name
if(name != NULL && (NULL == dev_name || !str_eq(bus->dirname, bus_name) || !str_eq(dev->filename, dev_name)))
continue;
pmsg_notice("found USBtiny with busdir:devicefile = %s:%s\n", bus->dirname, dev->filename);
// If -P usb:<busdir>:<devicefile> was given, skip non-matching busdir:devicefile
if(bus_name && dev_name)
if(!str_busdev_eq(bus->dirname, bus_name) || !str_busdev_eq(dev->filename, dev_name))
continue;
my.usb_handle = usb_open(dev); // Attempt to connect to device
// Wrong permissions or something?
@@ -341,10 +342,11 @@ static int usbtiny_open(PROGRAMMER *pgm, const char *name) {
}
}
if(NULL != name && NULL == dev_name) {
pmsg_error("invalid -P %s; use -P usb:bus:device\n", name);
if(bus_name && !dev_name) { // Delayed error message, so found devices are printed with -P usb:xyz
pmsg_error("invalid -P %s; drop -P option or use -P usb:<busdir>:<devicefile>\n", port);
return -1;
}
if(!my.usb_handle) {
pmsg_error("cannot find USBtiny device (0x%x/0x%x)\n", vid, pid);
return -1;