From 7ba818185beea876fe559af3a6409ce3a5e3cea7 Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Tue, 21 Oct 2025 13:37:32 +0200 Subject: [PATCH 01/56] Change notice about found USB devices --- src/doc/avrdude.texi | 16 ++++++++-------- src/usb_libusb.c | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index 520c47ab..156361e9 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -2199,16 +2199,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 @@ -5363,7 +5363,7 @@ 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 +(for example, @var{-P usb:xyz}), the scan will list all possible candidate devices found on the bus. Examples: diff --git a/src/usb_libusb.c b/src/usb_libusb.c index 62243ade..8977297a 100644 --- a/src/usb_libusb.c +++ b/src/usb_libusb.c @@ -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 From cec9cc8892c5d006957e929380fac2e220f2272a Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Tue, 21 Oct 2025 13:48:30 +0200 Subject: [PATCH 02/56] Reduce message level for found usbtiny devices to notice --- src/usbtiny.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/usbtiny.c b/src/usbtiny.c index 3b28e058..fbe2eff2 100644 --- a/src/usbtiny.c +++ b/src/usbtiny.c @@ -326,7 +326,7 @@ static int usbtiny_open(PROGRAMMER *pgm, const char *name) { 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); + pmsg_notice("found USBtiny with bus:device = %s:%s\n", 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; From 1f901210c752140267fed4108d8133de1a3c401c Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Tue, 21 Oct 2025 13:48:43 +0200 Subject: [PATCH 03/56] Reduce message level for found usbasp devices to notice --- src/usbasp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/usbasp.c b/src/usbasp.c index 86e01772..b58d62a5 100644 --- a/src/usbasp.c +++ b/src/usbasp.c @@ -420,7 +420,7 @@ static int usbasp_transmit(const PROGRAMMER *pgm, static int check_for_port_argument_match(const char *port, char *bus, char *device, char *serial_num) { - pmsg_debug("%s(): found USBasp, bus:device: %s:%s, serial_number: %s\n", __func__, bus, device, serial_num); + pmsg_notice("found USBasp with bus:device = %s:%s, serial_number = %s\n", bus, device, serial_num); const size_t usb_len = strlen("usb"); if(str_starts(port, "usb") && ':' == port[usb_len]) { From 881c8f80aa66083ac49fa76834040c3aceed19e8 Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Tue, 21 Oct 2025 13:58:24 +0200 Subject: [PATCH 04/56] Provide str_busdev_eq() function --- src/libavrdude.h | 1 + src/strutil.c | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/libavrdude.h b/src/libavrdude.h index dc10882d..67fe00e9 100644 --- a/src/libavrdude.h +++ b/src/libavrdude.h @@ -1678,6 +1678,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))) diff --git a/src/strutil.c b/src/strutil.c index d58f0c28..fcb12232 100644 --- a/src/strutil.c +++ b/src/strutil.c @@ -241,6 +241,23 @@ int str_is_in_list(const char *s, const char **l, size_t nl, int (*f)(const char return 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(*s >= '0' && *s <='9' && *t >= '0' && *t <='9') // Both look like a decimal number + 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; From 88eea2f90830b31d13a1459cda9a5fe70637ee41 Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Tue, 21 Oct 2025 14:04:19 +0200 Subject: [PATCH 05/56] Match bus:device for usbasp using str_busdev_eq() --- src/usbasp.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/src/usbasp.c b/src/usbasp.c index b58d62a5..21700566 100644 --- a/src/usbasp.c +++ b/src/usbasp.c @@ -418,22 +418,19 @@ 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_notice("found USBasp with bus:device = %s:%s, serial_number = %s\n", bus, device, serial_num); const size_t usb_len = strlen("usb"); if(str_starts(port, "usb") && ':' == port[usb_len]) { port += usb_len + 1; - char *colon_pointer = strchr(port, ':'); + char *dev_name = strchr(port, ':'); + + if(dev_name) // Compare with bus:device + 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); } @@ -514,12 +511,11 @@ static int usbOpenDevice(const PROGRAMMER *pgm, libusb_device_handle **device, i // -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; } @@ -644,12 +640,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 */ From edbdc25dc0e133f861e7e7b01489d4dc9e8ca914 Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Tue, 21 Oct 2025 14:04:46 +0200 Subject: [PATCH 06/56] Match bus:device for usbtiny using str_busdev_eq() --- src/usbtiny.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/usbtiny.c b/src/usbtiny.c index fbe2eff2..23e205f4 100644 --- a/src/usbtiny.c +++ b/src/usbtiny.c @@ -282,8 +282,7 @@ static int usbtiny_avr_op(const PROGRAMMER *pgm, const AVRPART *p, int op, unsig static int usbtiny_open(PROGRAMMER *pgm, const char *name) { 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 @@ -296,8 +295,6 @@ static int usbtiny_open(PROGRAMMER *pgm, const char *name) { 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'; } } @@ -322,13 +319,13 @@ 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_notice("found USBtiny with bus:device = %s:%s\n", 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))) + if(name && (!dev_name || !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 From 3139187915c53630d3db006ab2f6e4734690e959 Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Tue, 21 Oct 2025 14:38:30 +0200 Subject: [PATCH 07/56] Update documentation on multiple usbasp/usbtiny devices --- src/doc/avrdude.texi | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index 156361e9..b3b52f59 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -5350,20 +5350,18 @@ The pin mapping for the JTAG-to-ISP adapter is: @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. +Solution: The @var{-c usbtiny} programmer supports distinguishing multiple +physical USBtinyISP devices based on their bus:device pairs that describes +their place in the USB hierarchy on a specific host. This pair can be +specified in the @var{-P usb::} option. 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:xyz}), the scan will list all possible +By specifying a string that cannot match any existing device, +for example, @var{-P usb:xyz}, the scan will list all possible candidate devices found on the bus. Examples: @@ -5374,7 +5372,7 @@ 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, +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'). @example From 12a16d64c91ff1acd6cb39e0e45cf73dd560e778 Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Wed, 22 Oct 2025 11:44:31 +0200 Subject: [PATCH 08/56] Fix usbtiny device name comparison --- src/usbtiny.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/usbtiny.c b/src/usbtiny.c index 23e205f4..6345b099 100644 --- a/src/usbtiny.c +++ b/src/usbtiny.c @@ -325,7 +325,7 @@ static int usbtiny_open(PROGRAMMER *pgm, const char *name) { if(dev->descriptor.idVendor == vid && dev->descriptor.idProduct == pid) { // Found match? pmsg_notice("found USBtiny with bus:device = %s:%s\n", bus->dirname, dev->filename); // If -P was given, match device by device name and bus name - if(name && (!dev_name || !str_busdev_eq(bus->dirname, bus_name) || !str_busdev_eq(dev->filename, dev_name))) + if(name && (!dev_name || !str_busdev_eq(bus->dirname, bus_name) || !str_busdev_eq(dev->filename, dev_name+1))) continue; my.usb_handle = usb_open(dev); // Attempt to connect to device From b1d2f19ac197a139df5481eab5b307468749b75d Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Wed, 22 Oct 2025 12:56:22 +0200 Subject: [PATCH 09/56] Update JTAG EEPROM write troubleshooting --- src/doc/avrdude.texi | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index b3b52f59..2ccec762 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -5289,22 +5289,21 @@ 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? From b46cf675184dfb16825d05e379f34e707f303dc1 Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Wed, 22 Oct 2025 12:59:06 +0200 Subject: [PATCH 10/56] Update AVR910 slow-speed troubleshooting --- src/doc/avrdude.texi | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index 2ccec762..fa1c7222 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -5264,9 +5264,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 +5274,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,7 +5283,7 @@ 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} From 4f35f929cf5962a179b6d3be547be713a7659ec8 Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Wed, 22 Oct 2025 13:01:51 +0200 Subject: [PATCH 11/56] Indent JTAG to ISP pin table --- src/doc/avrdude.texi | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index fa1c7222..a981ecf7 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -5334,17 +5334,16 @@ 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. - 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 From 4303a45f74f382eb96b389f09db8ac0ee7ac567c Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Wed, 22 Oct 2025 13:29:21 +0200 Subject: [PATCH 12/56] Update multiple-USB-programmers troubleshooting --- src/doc/avrdude.texi | 55 +++++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index a981ecf7..81ba9150 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -3691,7 +3691,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. @@ -5347,35 +5347,42 @@ The pin mapping for the JTAG-to-ISP adapter is: @end multitable @item -Problem: Differentiate Multiple USBtinyISP (or USBasp) programmers +Problem: Differentiate multiple USBtinyISP (or USBasp) programmers -Solution: The @var{-c usbtiny} programmer supports distinguishing multiple -physical USBtinyISP devices based on their bus:device pairs that describes -their place in the USB hierarchy on a specific host. This pair can be -specified in the @var{-P usb::} option. +Solution: The @var{-c usbtiny} programmer distinguishes multiple physical +USBtinyISP devices based on their bus:device pairs that describe their +place in the USB hierarchy on a specific host. This pair can be specified +in the @var{-P usb::} option. -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:xyz}, 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'). +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 +@var{-P} option will need appropriate quoting on the command line, eg, +in bash with single quotes. + +For USBasp the same @var{-P usb::} as with USBtiny selects +the right device. Alternatively, USBasp can select the device via its +serial number using @var{-P usb:}. + +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 bus:device = 001:008, serial_number = 0001 +Found USBasp with bus:device = 001:009, serial_number = 1234 + +$ avrdude -qq -c USBasp -p atmega8 -P usb:1234 +@end example @item Problem: I cannot do @dots{} when the target is in debugWIRE mode. From b046c2514e60fdb6bb2e5e978b5b6132b38b2875 Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Wed, 22 Oct 2025 14:12:22 +0200 Subject: [PATCH 13/56] Clarify documentation on -P --- src/avrdude.1 | 31 ++++++++++++++++++++------ src/doc/avrdude.texi | 52 ++++++++++++++++++++++++-------------------- 2 files changed, 52 insertions(+), 31 deletions(-) diff --git a/src/avrdude.1 b/src/avrdude.1 index 6b8e197a..1729e59d 100644 --- a/src/avrdude.1 +++ b/src/avrdude.1 @@ -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,12 @@ 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. +.Pp If .Nm has been configured with libserialport support, a serial port can be specified @@ -663,20 +669,31 @@ 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::. +.Pp +For USBasp, multiple devices can also be also distinguished using -P +usb:: or using the serial number -P usb:. For +examples, see the respective .Em Troubleshooting -entry in the detailed documentation for examples. +entry in the detailed pdf documentation. .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 @@ -1639,7 +1656,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 diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index 81ba9150..575026de 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -824,6 +824,12 @@ 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 +@var{avrdude.conf} or @var{.avrduderc}. Only when there are multiple +programmers of the same type plugged into the host computer is the +@code{-P} option needed, see below. + 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 @@ -842,31 +848,31 @@ 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::}. + +For USBasp, multiple devices can also be also distinguished using @code{-P +usb::} or using the serial number @code{-P usb:}. For +examples, see the respective entry in @ref{Troubleshooting}. 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 +883,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 +903,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 From 475a507f91257f647580b96e44697d58d34e3975 Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Wed, 22 Oct 2025 15:39:46 +0200 Subject: [PATCH 14/56] Replace @var with @code for literal constants --- src/doc/avrdude.texi | 55 ++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index 575026de..b29c8f49 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -826,13 +826,13 @@ 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 -@var{avrdude.conf} or @var{.avrduderc}. Only when there are multiple +@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. 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 @@ -3126,11 +3126,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 @@ -5309,10 +5309,10 @@ 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 @@ -5321,9 +5321,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. @@ -5331,13 +5331,13 @@ 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 0.1 .1 .1 @@ -5353,11 +5353,10 @@ The pin mapping for the JTAG-to-ISP adapter is: @item Problem: Differentiate multiple USBtinyISP (or USBasp) programmers -Solution: The @var{-c usbtiny} programmer distinguishes multiple physical +Solution: The @code{-c usbtiny} programmer distinguishes multiple physical USBtinyISP devices based on their bus:device pairs that describe their place in the USB hierarchy on a specific host. This pair can be specified -in the @var{-P usb::} option. - +in the @code{-P usb::} option. The naming convention for the bus and device depends on the operating system. Examples for Linux, FreeBSD and Windows, respectively: @@ -5369,12 +5368,12 @@ $ avrdude -c usbtiny -p atmega8 \ @end example The Windows device name contains the backslash file separator, so the -@var{-P} option will need appropriate quoting on the command line, eg, +@code{-P} option will need appropriate quoting on the command line, eg, in bash with single quotes. -For USBasp the same @var{-P usb::} as with USBtiny selects +For USBasp the same @code{-P usb::} as with USBtiny selects the right device. Alternatively, USBasp can select the device via its -serial number using @var{-P usb:}. +serial number using @code{-P usb:}. Note that @code{avrdude -v -P usb:xyz} will print out suitable programmers on the bus assuming xyz does not match any device. @@ -5395,8 +5394,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. @@ -5479,13 +5478,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 @@ -5493,7 +5492,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): @@ -5551,7 +5550,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 From 22e3befe2b090b19711082217891a01c8dc181f6 Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Wed, 22 Oct 2025 17:40:04 +0200 Subject: [PATCH 15/56] Stylistic changes in texinfo documentation --- src/doc/avrdude.texi | 60 ++++++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index b29c8f49..bc504a0a 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -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=} 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{/../etc/avrdude.conf} +@code{@var{directory from which application loaded}/../etc/avrdude.conf} @item -@code{/avrdude.conf} +@code{@var{directory from which application loaded}/avrdude.conf} @end enumerate @@ -868,10 +868,10 @@ Mac OS but not on Windows. For more information about AVR-Doper see 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::}. +USB hierarchy using @code{-P usb:@var{bus}:@var{device}}. For USBasp, multiple devices can also be also distinguished using @code{-P -usb::} or using the serial number @code{-P usb:}. For +usb:@var{bus}:@var{device}} or using the serial number @code{-P usb:@var{serial}}. For examples, see the respective entry in @ref{Troubleshooting}. For the XBee programmer the target MCU is to be programmed wirelessly @@ -1313,8 +1313,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= -Shortcut for @code{-x init -x seed=} (see below) +@item init=@var{n} +Shortcut for @code{-x init -x seed=@var{n}} (see below) @cindex @code{flash} @item random @@ -1323,10 +1323,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= -Shortcut for @code{-x random -x seed=} +@item random=@var{n} +Shortcut for @code{-x random -x seed=@var{n}} -@item seed= +@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 @@ -1522,7 +1522,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. @@ -1575,7 +1575,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 @@ -1600,10 +1600,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=.. +@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=..} 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. @@ -1617,8 +1617,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= -When set, 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 @@ -1641,7 +1641,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= +@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 @@ -1649,7 +1649,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= +@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 @@ -1715,9 +1715,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= -Add a ms delay after reset. This can be useful if a board takes a -particularly long time to exit from external reset. 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 @@ -1867,13 +1867,13 @@ device is plugged in. The Wiring programmer type accepts the following extended parameters: @table @code -@item snooze= +@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= -Add a milliseconds delay after reset. This can be useful if a board -takes a particularly long time to exit from external reset. 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 @@ -1925,7 +1925,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 @@ -2258,7 +2258,7 @@ Valid commands: For more details about a terminal command cmd type cmd -? Other: - ! : run the shell 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 @@ -5356,7 +5356,7 @@ Problem: Differentiate multiple USBtinyISP (or USBasp) programmers Solution: The @code{-c usbtiny} programmer distinguishes multiple physical USBtinyISP devices based on their bus:device pairs that describe their place in the USB hierarchy on a specific host. This pair can be specified -in the @code{-P usb::} option. +in the @code{-P usb:@var{bus}:@var{device}} option. The naming convention for the bus and device depends on the operating system. Examples for Linux, FreeBSD and Windows, respectively: @@ -5371,9 +5371,9 @@ 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::} as with USBtiny selects +For USBasp the same @code{-P usb:@var{bus}:@var{device}} as with USBtiny selects the right device. Alternatively, USBasp can select the device via its -serial number using @code{-P usb:}. +serial number using @code{-P usb:@var{serial}}. Note that @code{avrdude -v -P usb:xyz} will print out suitable programmers on the bus assuming xyz does not match any device. From ab784e9edabe64a02858eed5abbfcb53ba2440fb Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Wed, 22 Oct 2025 20:43:13 +0200 Subject: [PATCH 16/56] Indent spifreq table --- src/doc/avrdude.texi | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index bc504a0a..e468e98b 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -1754,15 +1754,15 @@ 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 From c35c5f3074f237ba42001bedbbb28ac3b7c75e20 Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Wed, 22 Oct 2025 20:45:18 +0200 Subject: [PATCH 17/56] Indent and beautify the rawfreq table --- src/doc/avrdude.texi | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index e468e98b..66176de8 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -1769,11 +1769,11 @@ with programming the AVR in the other design. 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 From 48abc96d2b46876c27599300993945e8abf7f2a2 Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Wed, 22 Oct 2025 20:46:57 +0200 Subject: [PATCH 18/56] Indent and beautify the pickit2 connection table --- src/doc/avrdude.texi | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index 66176de8..e81141d6 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -1885,14 +1885,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: From c2e86d222986b4d528b6f6df4fbcaf0f47cfb14e Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Wed, 22 Oct 2025 22:35:55 +0200 Subject: [PATCH 19/56] Expand addr/len table for memory intervals --- src/avrdude.1 | 29 +++++++++++++--- src/doc/avrdude.texi | 80 ++++++++++++++++++++++---------------------- 2 files changed, 65 insertions(+), 44 deletions(-) diff --git a/src/avrdude.1 b/src/avrdude.1 index 1729e59d..f39223c1 100644 --- a/src/avrdude.1 +++ b/src/avrdude.1 @@ -985,10 +985,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 @@ -999,6 +1002,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 @@ -1006,6 +1022,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: diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index e81141d6..9eea3f46 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -2556,64 +2556,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: From cda38d2876d6a12e9b52fcdd1e006744e1037e57 Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Wed, 22 Oct 2025 22:40:42 +0200 Subject: [PATCH 20/56] Ensure memory segments stay within bounds --- src/fileio.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/fileio.c b/src/fileio.c index e0754f6a..c0feeac5 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -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; From ef3e37d37ab1d3df2f60fa8a1bd6d99c5f991af5 Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Wed, 22 Oct 2025 22:47:34 +0200 Subject: [PATCH 21/56] Indent data type table --- src/doc/avrdude.texi | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index 9eea3f46..ff045996 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -2797,62 +2797,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 From 0af648f129d627bae758b2f7a88a5c111eb3482c Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Wed, 22 Oct 2025 23:16:08 +0200 Subject: [PATCH 22/56] Indent data suffix table --- src/doc/avrdude.texi | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index ff045996..7b3f5d77 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -2872,14 +2872,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 From 4af43494f4e5439f8de538c7e800389d4e009542 Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Wed, 22 Oct 2025 23:17:43 +0200 Subject: [PATCH 23/56] Indent default-port table --- src/doc/avrdude.texi | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index 7b3f5d77..a6daa8a6 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -4909,17 +4909,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 From 01f8b9c4a3891b6fd06931f2591e0ba9566f9e0b Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Wed, 22 Oct 2025 23:23:51 +0200 Subject: [PATCH 24/56] Indent JTAG ICE PDI adapter table --- src/doc/avrdude.texi | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index a6daa8a6..4c4e83cf 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -5424,19 +5424,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 From 5f4afb21f9e792f393a8ef57371f290dca2baf46 Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Wed, 22 Oct 2025 23:25:12 +0200 Subject: [PATCH 25/56] Indent Dragon PDI adapter table --- src/doc/avrdude.texi | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index 4c4e83cf..4a8a76af 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -5445,15 +5445,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 From 27a5434b59260eff612bf0298ff1ea51bc1ce2de Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Wed, 22 Oct 2025 23:49:53 +0200 Subject: [PATCH 26/56] Indent AVRISP-TPI-conection table --- src/doc/avrdude.texi | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index 4a8a76af..e6aa0067 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -5462,15 +5462,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 @@ -5519,7 +5519,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 @@ -5575,8 +5575,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 From ae742bda5fb6cbd2dd944ab90435f5cc30d2b074 Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Thu, 23 Oct 2025 12:06:58 +0200 Subject: [PATCH 27/56] Remove unnecessary -P port parsing --- src/teensy.c | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/src/teensy.c b/src/teensy.c index ef6bdc76..35c876b8 100644 --- a/src/teensy.c +++ b/src/teensy.c @@ -305,34 +305,13 @@ 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(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; From 982af16f726bc85898a503f3c819b89bd8b0c56a Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Thu, 23 Oct 2025 12:07:08 +0200 Subject: [PATCH 28/56] Simplify micronucleus -P port handling --- src/micronucleus.c | 42 ++++++++++++++++-------------------------- 1 file changed, 16 insertions(+), 26 deletions(-) diff --git a/src/micronucleus.c b/src/micronucleus.c index 7f015c20..d2e0a5b7 100644 --- a/src/micronucleus.c +++ b/src/micronucleus.c @@ -577,34 +577,21 @@ 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++; - } - } + // Calculate bus and device names from -P usb:: option if present + if(str_starts(port, "usb:")) { + bus_name = port + 4; + if((dev_name = strchr(bus_name, ':'))) + 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: MICRONUCLEUS_VID; int pid = MICRONUCLEUS_PID; @@ -652,15 +639,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, bus:device = %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:: was given, skip non-matching bus:device + 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 +682,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; use -P usb::\n", port); + return -1; + } + if(!pdata->usb_handle) { pmsg_error("cannot find device with Micronucleus bootloader (%04X:%04X)\n", vid, pid); return -1; From 7af83b47cee782af9fc9d38d9a07b7f0e1efff46 Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Thu, 23 Oct 2025 12:28:36 +0200 Subject: [PATCH 29/56] Simplify usbtiny -P port parsing --- src/usbtiny.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/usbtiny.c b/src/usbtiny.c index 6345b099..6e027e88 100644 --- a/src/usbtiny.c +++ b/src/usbtiny.c @@ -279,23 +279,19 @@ 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, *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, ':'); - } + // Calculate bus and device names from -P usb:: 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 @@ -324,9 +320,12 @@ static int usbtiny_open(PROGRAMMER *pgm, const char *name) { for(dev = bus->devices; dev; dev = dev->next) { if(dev->descriptor.idVendor == vid && dev->descriptor.idProduct == pid) { // Found match? pmsg_notice("found USBtiny with bus:device = %s:%s\n", bus->dirname, dev->filename); - // If -P was given, match device by device name and bus name - if(name && (!dev_name || !str_busdev_eq(bus->dirname, bus_name) || !str_busdev_eq(dev->filename, dev_name+1))) - continue; + + // If -P usb:: was given, skip non-matching bus:device + 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? @@ -338,10 +337,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; use -P usb::\n", port); return -1; } + if(!my.usb_handle) { pmsg_error("cannot find USBtiny device (0x%x/0x%x)\n", vid, pid); return -1; From 2d63a1947a9107d780ef15b8c3abd0ebd9ca8b0d Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Thu, 23 Oct 2025 12:32:36 +0200 Subject: [PATCH 30/56] Simplify usbasp -P port parsing --- src/usbasp.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/usbasp.c b/src/usbasp.c index 21700566..873fecbc 100644 --- a/src/usbasp.c +++ b/src/usbasp.c @@ -422,10 +422,9 @@ static int check_for_port_argument_match(const char *port, const char *bus, const char *device, const char *serial_num) { pmsg_notice("found USBasp with bus:device = %s:%s, serial_number = %s\n", bus, device, serial_num); - const size_t usb_len = strlen("usb"); - if(str_starts(port, "usb") && ':' == port[usb_len]) { - port += usb_len + 1; + if(str_starts(port, "usb:")) { + port += 4; char *dev_name = strchr(port, ':'); if(dev_name) // Compare with bus:device @@ -478,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) { @@ -489,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) @@ -507,7 +506,7 @@ 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)); @@ -616,7 +615,7 @@ 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"); From f3009e7348c70c53646a1f81f5d18d93be8574e0 Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Thu, 23 Oct 2025 12:35:46 +0200 Subject: [PATCH 31/56] Document that usbasp serial number is matched from end --- src/doc/avrdude.texi | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index e6aa0067..9fcc5670 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -871,8 +871,10 @@ numbers, multiple devices can be distinguished by their location in the USB hierarchy using @code{-P usb:@var{bus}:@var{device}}. For USBasp, multiple devices can also be also distinguished using @code{-P -usb:@var{bus}:@var{device}} or using the serial number @code{-P usb:@var{serial}}. For -examples, see the respective entry in @ref{Troubleshooting}. +usb:@var{bus}:@var{device}} or using the serial number @code{-P +usb:@var{serial}}. 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}. For the XBee programmer the target MCU is to be programmed wirelessly over a ZigBee mesh using the XBeeBoot bootloader. The ZigBee 64-bit @@ -5384,7 +5386,7 @@ $ avrdude -v -Pusb:xyz -c usbasp -p m328p 2>&1 | grep ^Found Found USBasp with bus:device = 001:008, serial_number = 0001 Found USBasp with bus:device = 001:009, serial_number = 1234 -$ avrdude -qq -c USBasp -p atmega8 -P usb:1234 +$ avrdude -qq -c USBasp -p atmega8 -P usb:34 @end example @item From a6553e80d3fb3048e3e2b5aabf3d69a1f36b807b Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Thu, 23 Oct 2025 13:39:40 +0200 Subject: [PATCH 32/56] Sharpen test for bus/device number --- src/strutil.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/strutil.c b/src/strutil.c index fcb12232..36c02281 100644 --- a/src/strutil.c +++ b/src/strutil.c @@ -241,9 +241,19 @@ 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(*s >= '0' && *s <='9' && *t >= '0' && *t <='9') // Both look like a decimal number + if(is_busdev_num(s) && is_busdev_num(t)) if(strtoull(s, NULL, 10) == strtoull(t, NULL, 10)) return 1; From f44301d5bc2e9c6acaeff1fca8cd80ecf1563590 Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Thu, 23 Oct 2025 14:44:12 +0200 Subject: [PATCH 33/56] Allow pickit5 vid/pid be specified as 0 --- src/pickit5.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/pickit5.c b/src/pickit5.c index 53e970d6..01969554 100644 --- a/src/pickit5.c +++ b/src/pickit5.c @@ -579,12 +579,12 @@ static int pickit5_open(PROGRAMMER *pgm, const char *port) { return -1; #endif - if(!str_starts(port, "usb")) { - pmsg_error("port names must start with usb\n"); + if(!str_starts(port, "usb:") && !str_eq(port, "usb")) { + pmsg_error("port name %s must be usb:: or usb:\n", port); return -1; } - 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: @@ -608,6 +608,7 @@ 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) { @@ -624,10 +625,8 @@ static int pickit5_open(PROGRAMMER *pgm, const char *port) { return -1; } - 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 - } + 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' @@ -639,7 +638,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; From d759b35a718bbbd7782d66c51d6379936a824c61 Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Thu, 23 Oct 2025 15:00:48 +0200 Subject: [PATCH 34/56] Document pickit5 -P port use --- src/avrdude.1 | 9 ++++++++- src/doc/avrdude.texi | 12 ++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/avrdude.1 b/src/avrdude.1 index f39223c1..cd98507c 100644 --- a/src/avrdude.1 +++ b/src/avrdude.1 @@ -690,11 +690,18 @@ numbers, multiple devices can be distinguished by their location in the USB hierarchy using -P usb::. .Pp For USBasp, multiple devices can also be also distinguished using -P -usb:: or using the serial number -P usb:. For +usb:: or using the serial number -P usb:. For examples, see the respective .Em Troubleshooting entry in the detailed pdf documentation. .Pp +The -c pickit5 programmer allows overriding the product ID with a +hexadecimal number using -P usb:: and the vendor and product +IDs with hexadecimal numbers and using -P usb::. The +form -P usb: requests AVRDUDE select the PICkit5 programmer with +a serial number that ends in (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 target MCU's own XBee device must be supplied as a 16-character hexadecimal diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index 9fcc5670..ca8954ce 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -872,10 +872,18 @@ USB hierarchy using @code{-P usb:@var{bus}:@var{device}}. For USBasp, multiple devices can also be also distinguished using @code{-P usb:@var{bus}:@var{device}} or using the serial number @code{-P -usb:@var{serial}}. The USBasp serial number is matched from the end, so +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 address for the target MCU's own XBee device must be supplied as a @@ -5375,7 +5383,7 @@ in bash with single quotes. For USBasp the same @code{-P usb:@var{bus}:@var{device}} as with USBtiny selects the right device. Alternatively, USBasp can select the device via its -serial number using @code{-P usb:@var{serial}}. +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. From 37a52cc401a6392b8b5153218e4b229941ecafa9 Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Thu, 23 Oct 2025 15:23:16 +0200 Subject: [PATCH 35/56] Utilise str_busdev_eq() in dfu.c --- src/dfu.c | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/src/dfu.c b/src/dfu.c index 6bf51a56..1cb15747 100644 --- a/src/dfu.c +++ b/src/dfu.c @@ -92,8 +92,7 @@ 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 @@ -101,16 +100,15 @@ struct dfu_dev *dfu_open(const char *port_spec) { * 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); + if(!str_starts(port_spec, "usb:") && !str_eq(port_spec, "usb")) { + pmsg_error("port name %s must be usb::\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'; } @@ -148,7 +146,7 @@ int dfu_init(struct dfu_dev *dfu, unsigned short vid, unsigned short pid) { */ 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 in config or USB address via -P usb::\n"); return -1; } @@ -164,10 +162,10 @@ 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(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; @@ -223,14 +221,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) { From 0982d8d149174b1c7964a682e6cc331a63284fdd Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Thu, 23 Oct 2025 15:33:58 +0200 Subject: [PATCH 36/56] Print error message on wrong -P use for usbasp --- src/usbasp.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/usbasp.c b/src/usbasp.c index 873fecbc..034659fe 100644 --- a/src/usbasp.c +++ b/src/usbasp.c @@ -649,6 +649,11 @@ static int usbasp_open(PROGRAMMER *pgm, const char *port) { */ } + if(!str_starts(port, "usb:") && !str_eq(port, "usb")) { + pmsg_error("invalid -P %s; use -P usb:: or -P usb:\n", port); + return -1; + } + pmsg_error("cannot find USB device with vid=0x%x pid=0x%x", vid, pid); if(pgm->usbvendor && *pgm->usbvendor) msg_error(" vendor='%s'", pgm->usbvendor); From f084de37e6b218ba07e0ffe5fa29f2f0ecc6c24f Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Thu, 23 Oct 2025 15:51:53 +0200 Subject: [PATCH 37/56] print notice when dfu device found --- src/dfu.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/dfu.c b/src/dfu.c index 1cb15747..2334c687 100644 --- a/src/dfu.c +++ b/src/dfu.c @@ -162,6 +162,10 @@ 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(vid == dev->descriptor.idVendor && pid == dev->descriptor.idProduct) + pmsg_notice("found device with vendorID=0x%04x and productID=0x%04x, bus:device = %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) { From d412131df522c47fc7a98414e1a1ee9a92efa779 Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Thu, 23 Oct 2025 23:39:59 +0200 Subject: [PATCH 38/56] Improve messaging --- src/dfu.c | 4 ++-- src/micronucleus.c | 7 ++++++- src/pickit5.c | 6 +++--- src/usbasp.c | 10 +++++----- src/usbtiny.c | 7 ++++++- 5 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/dfu.c b/src/dfu.c index 2334c687..a5d21d8a 100644 --- a/src/dfu.c +++ b/src/dfu.c @@ -101,7 +101,7 @@ struct dfu_dev *dfu_open(const char *port_spec) { */ if(!str_starts(port_spec, "usb:") && !str_eq(port_spec, "usb")) { - pmsg_error("port name %s must be usb::\n", port_spec); + pmsg_error("invalid -P %s; drop this option or use -P usb::\n", port_spec); return NULL; } @@ -146,7 +146,7 @@ int dfu_init(struct dfu_dev *dfu, unsigned short vid, unsigned short pid) { */ if(pid == 0 && dfu->dev_name == NULL) { - pmsg_error("no DFU support for part; specify in config or USB address via -P usb::\n"); + pmsg_error("no DFU support for part; specify in config or USB address via -P usb::\n"); return -1; } diff --git a/src/micronucleus.c b/src/micronucleus.c index d2e0a5b7..e3186aaa 100644 --- a/src/micronucleus.c +++ b/src/micronucleus.c @@ -585,6 +585,11 @@ static int micronucleus_open(PROGRAMMER *pgm, const char *port) { struct pdata *pdata = &my; const char *bus_name = NULL, *dev_name = NULL; + if(!str_starts(port, "usb:") && !str_eq(port, "usb")) { + pmsg_error("invalid -P %s; drop this option or use -P usb::\n", port); + return -1; + } + // Calculate bus and device names from -P usb:: option if present if(str_starts(port, "usb:")) { bus_name = port + 4; @@ -683,7 +688,7 @@ static int micronucleus_open(PROGRAMMER *pgm, const char *port) { } if(bus_name && !dev_name) { // Delayed error message, so found devices are printed with -P usb:xyz - pmsg_error("invalid -P %s; use -P usb::\n", port); + pmsg_error("invalid -P %s; use -P usb:: or -P usb\n", port); return -1; } diff --git a/src/pickit5.c b/src/pickit5.c index 01969554..ce9b8ce0 100644 --- a/src/pickit5.c +++ b/src/pickit5.c @@ -580,7 +580,7 @@ static int pickit5_open(PROGRAMMER *pgm, const char *port) { #endif if(!str_starts(port, "usb:") && !str_eq(port, "usb")) { - pmsg_error("port name %s must be usb:: or usb:\n", port); + pmsg_error("invalid -P %s; use -P usb::, -P usb: or -P usb\n", port); return -1; } unsigned int new_vid = 0, new_pid = 0, setids = 0; @@ -612,7 +612,7 @@ static int pickit5_open(PROGRAMMER *pgm, const char *port) { 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); + pmsg_error("failed to parse -P VID input %s: expected hexadecimal number\n", vidp); return -1; } } else { // VID space empty: default to Microchip @@ -621,7 +621,7 @@ 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); + pmsg_error("failed to parse -P PID input %s: expected hexadecimal number\n", pidp+1); return -1; } diff --git a/src/usbasp.c b/src/usbasp.c index 034659fe..7aefafb9 100644 --- a/src/usbasp.c +++ b/src/usbasp.c @@ -620,6 +620,11 @@ static int usbasp_open(PROGRAMMER *pgm, const char *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; use -P usb::, -P usb: or -P usb\n", port); + return -1; + } + // usb_init will be done in usbOpenDevice LNODEID usbpid = lfirst(pgm->usbpid); int pid, vid; @@ -649,11 +654,6 @@ static int usbasp_open(PROGRAMMER *pgm, const char *port) { */ } - if(!str_starts(port, "usb:") && !str_eq(port, "usb")) { - pmsg_error("invalid -P %s; use -P usb:: or -P usb:\n", port); - return -1; - } - pmsg_error("cannot find USB device with vid=0x%x pid=0x%x", vid, pid); if(pgm->usbvendor && *pgm->usbvendor) msg_error(" vendor='%s'", pgm->usbvendor); diff --git a/src/usbtiny.c b/src/usbtiny.c index 6e027e88..f2b493e0 100644 --- a/src/usbtiny.c +++ b/src/usbtiny.c @@ -287,6 +287,11 @@ static int usbtiny_open(PROGRAMMER *pgm, const char *port) { pmsg_debug("%s(\"%s\")\n", __func__, port); + if(!str_starts(port, "usb:") && !str_eq(port, "usb")) { + pmsg_error("invalid -P %s; drop this option or use -P usb::\n", port); + return -1; + } + // Calculate bus and device names from -P usb:: option if present if(str_starts(port, "usb:")) { bus_name = port + 4; @@ -338,7 +343,7 @@ static int usbtiny_open(PROGRAMMER *pgm, const char *port) { } if(bus_name && !dev_name) { // Delayed error message, so found devices are printed with -P usb:xyz - pmsg_error("invalid -P %s; use -P usb::\n", port); + pmsg_error("invalid -P %s; use -P usb:: or -P usb\n", port); return -1; } From af58933372e52b5b14022fe03e31ca8cf9eeb9e1 Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Fri, 24 Oct 2025 10:27:37 +0200 Subject: [PATCH 39/56] Warn that -P option is ignored for avrftdi --- src/avrftdi.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/avrftdi.c b/src/avrftdi.c index d0cbeccd..61dc4e45 100644 --- a/src/avrftdi.c +++ b/src/avrftdi.c @@ -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 From df5c1734eaa7d0b4aef2ce17f6316e4977945e7c Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Fri, 24 Oct 2025 10:29:25 +0200 Subject: [PATCH 40/56] Warn that -P option is ignored for ch341a --- src/ch341a.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ch341a.c b/src/ch341a.c index 653ffb1a..b719f5ac 100644 --- a/src/ch341a.c +++ b/src/ch341a.c @@ -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; From d296cb5bee6d469e93086b6076cec97ee98b3def Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Fri, 24 Oct 2025 10:39:22 +0200 Subject: [PATCH 41/56] Unify xxx_open() notice for jtagmkII --- src/jtagmkII.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/jtagmkII.c b/src/jtagmkII.c index 816faf8d..b72e45ae 100644 --- a/src/jtagmkII.c +++ b/src/jtagmkII.c @@ -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 From f197504b804e08541ac4b17e65b54fa3837b37e4 Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Fri, 24 Oct 2025 11:24:04 +0200 Subject: [PATCH 42/56] Unify xxx_open() debug message for flip1/2 --- src/dfu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/dfu.c b/src/dfu.c index a5d21d8a..ef467f38 100644 --- a/src/dfu.c +++ b/src/dfu.c @@ -100,6 +100,8 @@ struct dfu_dev *dfu_open(const char *port_spec) { * function, where we actually open the device. */ + 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::\n", port_spec); return NULL; From 37ef71b5a6bdcb3304724646971efe2cdbf89b3b Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Fri, 24 Oct 2025 11:25:32 +0200 Subject: [PATCH 43/56] Unify xxx_open() debug message for ft245r --- src/ft245r.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ft245r.c b/src/ft245r.c index 2cf7eff3..bcc4ad8c 100644 --- a/src/ft245r.c +++ b/src/ft245r.c @@ -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) { From 009aa3615f28c81b9064d588d2be9d9354a44ad6 Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Fri, 24 Oct 2025 11:33:00 +0200 Subject: [PATCH 44/56] Unify xxx_open() debug message for urclock --- src/urclock.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/urclock.c b/src/urclock.c index d5d2d86a..6cd0b1cd 100644 --- a/src/urclock.c +++ b/src/urclock.c @@ -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; From 6e59b6dd10bf28457653858b620c411709b26068 Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Fri, 24 Oct 2025 11:35:03 +0200 Subject: [PATCH 45/56] Warn that -P option is ignored for pickit2 --- src/pickit2.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/pickit2.c b/src/pickit2.c index c75bd421..f0726f41 100644 --- a/src/pickit2.c +++ b/src/pickit2.c @@ -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); From ca36e3c47f54cdb2b539f88a8270ad4731a87981 Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Fri, 24 Oct 2025 11:36:28 +0200 Subject: [PATCH 46/56] Warn that -P option is ignored for teensy --- src/teensy.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/teensy.c b/src/teensy.c index 35c876b8..f427acc6 100644 --- a/src/teensy.c +++ b/src/teensy.c @@ -306,6 +306,8 @@ static int teensy_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) { static int teensy_open(PROGRAMMER *pgm, const char *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); From 0aeaa69ca906275b1623c84265e49eff45b1aa70 Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Mon, 27 Oct 2025 11:19:23 +0100 Subject: [PATCH 47/56] Rename bus:device to busdir:devicefile for dfu.c --- src/dfu.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/dfu.c b/src/dfu.c index ef467f38..f2a0c6fb 100644 --- a/src/dfu.c +++ b/src/dfu.c @@ -94,16 +94,17 @@ struct dfu_dev *dfu_open(const char *port_spec) { struct dfu_dev *dfu; 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::". We stash these + * away in the dfu_dev structure for the dfu_init() function, where we + * actually open the device. */ 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::\n", port_spec); + pmsg_error("invalid -P %s; drop this option or use -P usb::\n", port_spec); return NULL; } @@ -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:: + * (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 in config or USB address via -P usb::\n"); + pmsg_error("no DFU support for part; specify in config or USB address via -P usb::\n"); return -1; } @@ -165,7 +168,7 @@ 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(vid == dev->descriptor.idVendor && pid == dev->descriptor.idProduct) - pmsg_notice("found device with vendorID=0x%04x and productID=0x%04x, bus:device = %s:%s\n", + 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)) @@ -191,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); From a76b1b8773467a2c6f5d831155825c8b3909465c Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Mon, 27 Oct 2025 11:20:01 +0100 Subject: [PATCH 48/56] Rename bus:device to busdir:devicefile for micronucleus.c --- src/micronucleus.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/micronucleus.c b/src/micronucleus.c index e3186aaa..4d34de8d 100644 --- a/src/micronucleus.c +++ b/src/micronucleus.c @@ -586,11 +586,11 @@ static int micronucleus_open(PROGRAMMER *pgm, const char *port) { const char *bus_name = NULL, *dev_name = NULL; if(!str_starts(port, "usb:") && !str_eq(port, "usb")) { - pmsg_error("invalid -P %s; drop this option or use -P usb::\n", port); + pmsg_error("invalid -P %s; drop this option or use -P usb::\n", port); return -1; } - // Calculate bus and device names from -P usb:: option if present + // Calculate bus and device names from -P usb:: option if present if(str_starts(port, "usb:")) { bus_name = port + 4; if((dev_name = strchr(bus_name, ':'))) @@ -644,10 +644,10 @@ 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 usb:: was given, skip non-matching bus:device + // If -P usb:: 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; @@ -688,7 +688,7 @@ static int micronucleus_open(PROGRAMMER *pgm, const char *port) { } if(bus_name && !dev_name) { // Delayed error message, so found devices are printed with -P usb:xyz - pmsg_error("invalid -P %s; use -P usb:: or -P usb\n", port); + pmsg_error("invalid -P %s; drop -P option or use -P usb::\n", port); return -1; } From 1e29892abe17163a19d50ac4e96d27b700ec76ba Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Mon, 27 Oct 2025 11:21:01 +0100 Subject: [PATCH 49/56] Reword serial number message --- src/usb_libusb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/usb_libusb.c b/src/usb_libusb.c index 8977297a..94d80452 100644 --- a/src/usb_libusb.c +++ b/src/usb_libusb.c @@ -142,7 +142,7 @@ static int usbdev_open(const char *port, union pinfo pinfo, union filedescriptor fd->usb.wep = 0x02; } - pmsg_notice("found %s with serno: %s\n", 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 From 4390275fc1b42b7f9baf15dcd3a0dc590b331fad Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Mon, 27 Oct 2025 11:21:52 +0100 Subject: [PATCH 50/56] Rename bus:device to busdir:devicefile for usbasp.c --- src/usbasp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/usbasp.c b/src/usbasp.c index 7aefafb9..4f8e74e9 100644 --- a/src/usbasp.c +++ b/src/usbasp.c @@ -421,13 +421,13 @@ static int usbasp_transmit(const PROGRAMMER *pgm, static int check_for_port_argument_match(const char *port, const char *bus, const char *device, const char *serial_num) { - pmsg_notice("found USBasp with bus:device = %s:%s, serial_number = %s\n", bus, device, serial_num); + pmsg_notice("found USBasp with busdir:devicefile = %s:%s, serial_number = %s\n", bus, device, serial_num); if(str_starts(port, "usb:")) { port += 4; char *dev_name = strchr(port, ':'); - if(dev_name) // Compare with bus:device + if(dev_name) // Compare with busdir:devicefile return str_busdev_eq(port, bus) && str_busdev_eq(dev_name+1, device); // Serial number case @@ -621,7 +621,7 @@ static int usbasp_open(PROGRAMMER *pgm, const char *port) { 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; use -P usb::, -P usb: or -P usb\n", port); + pmsg_error("invalid -P %s; drop -P option or else use -P usb:: or -P usb:\n", port); return -1; } From 6e8d2f6b2a436e58b5753b8bda6fefe25ea63078 Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Mon, 27 Oct 2025 11:22:12 +0100 Subject: [PATCH 51/56] Rename bus:device to busdir:devicefile for usbtiny.c --- src/usbtiny.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/usbtiny.c b/src/usbtiny.c index f2b493e0..88f15831 100644 --- a/src/usbtiny.c +++ b/src/usbtiny.c @@ -288,11 +288,11 @@ static int usbtiny_open(PROGRAMMER *pgm, const char *port) { pmsg_debug("%s(\"%s\")\n", __func__, port); if(!str_starts(port, "usb:") && !str_eq(port, "usb")) { - pmsg_error("invalid -P %s; drop this option or use -P usb::\n", port); + pmsg_error("invalid -P %s; drop this option or use -P usb::\n", port); return -1; } - // Calculate bus and device names from -P usb:: option if present + // Calculate bus and device names from -P usb:: option if present if(str_starts(port, "usb:")) { bus_name = port + 4; if((dev_name = strchr(bus_name, ':'))) @@ -324,9 +324,9 @@ static int usbtiny_open(PROGRAMMER *pgm, const char *port) { 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_notice("found USBtiny with bus:device = %s:%s\n", bus->dirname, dev->filename); + pmsg_notice("found USBtiny with busdir:devicefile = %s:%s\n", bus->dirname, dev->filename); - // If -P usb:: was given, skip non-matching bus:device + // If -P usb:: 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; @@ -343,7 +343,7 @@ static int usbtiny_open(PROGRAMMER *pgm, const char *port) { } if(bus_name && !dev_name) { // Delayed error message, so found devices are printed with -P usb:xyz - pmsg_error("invalid -P %s; use -P usb:: or -P usb\n", port); + pmsg_error("invalid -P %s; drop -P option or use -P usb::\n", port); return -1; } From e499f0ba5ea27594e8014786f64e4d98c1493f1f Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Mon, 27 Oct 2025 11:22:43 +0100 Subject: [PATCH 52/56] Rename bus:device to busdir:devicefile in documentation --- src/avrdude.1 | 6 +++--- src/doc/avrdude.texi | 24 ++++++++++++------------ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/avrdude.1 b/src/avrdude.1 index cd98507c..567500d6 100644 --- a/src/avrdude.1 +++ b/src/avrdude.1 @@ -687,11 +687,11 @@ 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 using -P usb::. +USB hierarchy using -P usb::. .Pp For USBasp, multiple devices can also be also distinguished using -P -usb:: or using the serial number -P usb:. For -examples, see the respective +usb:: or using the serial number -P usb:. +For examples, see the respective .Em Troubleshooting entry in the detailed pdf documentation. .Pp diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index ca8954ce..6fa6747f 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -868,10 +868,10 @@ Mac OS but not on Windows. For more information about AVR-Doper see 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{bus}:@var{device}}. +USB hierarchy using @code{-P usb:@var{busdir}:@var{devicefile}}. For USBasp, multiple devices can also be also distinguished using @code{-P -usb:@var{bus}:@var{device}} or using the serial number @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}. @@ -5364,11 +5364,11 @@ The pin mapping for the JTAG-to-ISP adapter is: Problem: Differentiate multiple USBtinyISP (or USBasp) programmers Solution: The @code{-c usbtiny} programmer distinguishes multiple physical -USBtinyISP devices based on their bus:device pairs that describe their -place in the USB hierarchy on a specific host. This pair can be specified -in the @code{-P usb:@var{bus}:@var{device}} option. -The naming convention for the bus and device depends on the operating -system. Examples for Linux, FreeBSD and Windows, respectively: +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 usbtiny -p atmega8 -P usb:003:025 @@ -5381,9 +5381,9 @@ 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{bus}:@var{device}} as with USBtiny selects -the right device. Alternatively, USBasp can select the device via its -serial number using @code{-P usb:@var{serialno}}. +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. @@ -5391,8 +5391,8 @@ 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 bus:device = 001:008, serial_number = 0001 -Found USBasp with bus:device = 001:009, serial_number = 1234 +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 From 03b6a55af8197746ad779051af0f88d702db0737 Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Mon, 27 Oct 2025 11:29:09 +0100 Subject: [PATCH 53/56] Mention programmers that ignore -P option in documentation --- src/avrdude.1 | 4 +++- src/doc/avrdude.texi | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/avrdude.1 b/src/avrdude.1 index 567500d6..e38ac81f 100644 --- a/src/avrdude.1 +++ b/src/avrdude.1 @@ -611,7 +611,9 @@ 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. +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 diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index 6fa6747f..c0c37a0e 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -828,7 +828,9 @@ 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. +@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 From 7fa03f8306d8c6d9d021929c441b6ce99e8d5885 Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Thu, 30 Oct 2025 10:20:56 +0100 Subject: [PATCH 54/56] Adjust spacing --- src/pickit5.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/pickit5.c b/src/pickit5.c index ce9b8ce0..adbd855d 100644 --- a/src/pickit5.c +++ b/src/pickit5.c @@ -171,7 +171,7 @@ static int pickit5_jtag_write_fuse(const PROGRAMMER *pgm, const AVRPART *p, cons static int pickit5_jtag_read_fuse(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, unsigned char *value); // PDI-Specific -static int pickit5_pdi_flash_write(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, +static int pickit5_pdi_flash_write(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, unsigned long addr, int len, unsigned char *value); // Extra functions @@ -626,7 +626,7 @@ static int pickit5_open(PROGRAMMER *pgm, const char *port) { } pmsg_notice("overwriting VID:PID to %04x:%04x\n", new_vid, new_pid); - port = "usb"; // Overwrite the string to avoid confusing the libusb + port = "usb"; // Overwrite the string to avoid confusing the libusb } // pidp == NULL means vidp could point to serial number } // vidp == NULL means just 'usb' @@ -729,7 +729,7 @@ static int pickit5_open(PROGRAMMER *pgm, const char *port) { return LIBAVRDUDE_EXIT; } 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; } @@ -984,7 +984,7 @@ static int pickit5_initialize(const PROGRAMMER *pgm, const AVRPART *p) { // Now we try to figure out if we have to supply power from PICkit double v_target = 3.30; // Placeholder in case no VTARG Read - + if(pgm->extra_features & HAS_VTARG_READ) { // If not supported (PK Basic), use a place pickit5_get_vtarget(pgm, &v_target); if(v_target < 1.8) { @@ -1280,16 +1280,16 @@ static int pickit5_pdi_flash_write(const PROGRAMMER *pgm, const AVRPART *p, 0x6C, 0x0B, // Move temp_reg to r11 0x1E, 0x03, 0x05, // Load byte from NVM Data register (r05) 0x6C, 0x0C, // Move temp_reg to r12 - + 0x60, 0x03, 0x01, // copy r01 to r03 0x93, 0x03, page_size, (page_size >> 8), // Integer divide r03 by page size 0xAD, 0x03, // while (r03 --) { - + 0x1E, 0x06, 0x04, 0x07, // Load "load page command" to NVM Cmd Reg 0x1E, 0x09, 0x00, // Set pointer for indirect addressing to r00 0x1E, 0x10, 0x0A, // Set repeat counter to number in r09 0x1E, 0x0A, 0x0A, // read from data stream and send it to the device - + 0x1E, 0x06, 0x04, 0x08, // Load "Erase and write flash page" command into NVM Cmd buffer 0x1E, 0x06, 0x00, 0x09, // Triger NVM Cmd by writing to the first address (r0, 0xFF) 0xA2, // Do { @@ -1309,7 +1309,7 @@ static int pickit5_pdi_flash_write(const PROGRAMMER *pgm, const AVRPART *p, unsigned char param[8]; pickit5_uint32_to_array(¶m[0], addr); pickit5_uint32_to_array(¶m[4], len); - + int rc = pickit5_download_data(pgm, flash_cmd, sizeof(flash_cmd), param, sizeof(param), value, len); if(rc < 0) rc = LIBAVRDUDE_EXIT; @@ -1707,7 +1707,7 @@ static int pickit5_isp_write_fuse(const PROGRAMMER *pgm, const AVRMEM *mem, unsi // Support slow AVRs without write status polling (won't affect performance) int delay = mem->min_write_delay; if (delay > 0) - usleep(delay); + usleep(delay); return 1; } From e73695f0139a1f0c520c4c7abef421cc23119f8a Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Thu, 30 Oct 2025 10:28:23 +0100 Subject: [PATCH 55/56] Use symbolic return values in pickit5_open() --- src/pickit5.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/pickit5.c b/src/pickit5.c index adbd855d..8cb6e357 100644 --- a/src/pickit5.c +++ b/src/pickit5.c @@ -568,20 +568,20 @@ static int pickit5_upload_data(const PROGRAMMER *pgm, const unsigned char *scr, 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; #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:") && !str_eq(port, "usb")) { pmsg_error("invalid -P %s; use -P usb::, -P usb: or -P usb\n", port); - return -1; + return LIBAVRDUDE_GENERAL_FAILURE; } unsigned int new_vid = 0, new_pid = 0, setids = 0; const char *vidp, *pidp; @@ -613,7 +613,7 @@ static int pickit5_open(PROGRAMMER *pgm, const char *port) { // First: Handle VID input if(sscanf(vidp, "%x", &new_vid) != 1) { pmsg_error("failed to parse -P VID input %s: expected hexadecimal number\n", vidp); - return -1; + return LIBAVRDUDE_GENERAL_FAILURE; } } else { // VID space empty: default to Microchip new_vid = USB_VENDOR_MICROCHIP; @@ -622,7 +622,7 @@ 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: expected hexadecimal number\n", pidp+1); - return -1; + return LIBAVRDUDE_GENERAL_FAILURE; } pmsg_notice("overwriting VID:PID to %04x:%04x\n", new_vid, new_pid); From 0e87b1f7c963bd157e2def90a5feb10a729d43c8 Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Thu, 30 Oct 2025 10:31:28 +0100 Subject: [PATCH 56/56] Improve error messaging for serial number mismatch As advised by @MX682X --- src/pickit5.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/pickit5.c b/src/pickit5.c index 8cb6e357..d0cbb9c3 100644 --- a/src/pickit5.c +++ b/src/pickit5.c @@ -573,6 +573,7 @@ static int pickit5_open(PROGRAMMER *pgm, const char *port) { union pinfo pinfo; LNODEID usbpid; 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"); @@ -580,7 +581,7 @@ static int pickit5_open(PROGRAMMER *pgm, const char *port) { #endif if(!str_starts(port, "usb:") && !str_eq(port, "usb")) { - pmsg_error("invalid -P %s; use -P usb::, -P usb: or -P usb\n", port); + pmsg_error("invalid -P %s; drop -P option or else use -P usb:: or -P usb:\n", port); return LIBAVRDUDE_GENERAL_FAILURE; } unsigned int new_vid = 0, new_pid = 0, setids = 0; @@ -627,8 +628,10 @@ static int pickit5_open(PROGRAMMER *pgm, const char *port) { 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' + } 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) @@ -728,6 +731,11 @@ 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); 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);