Closed MCUdude closed 9 months ago
A USB traffic capture (when running MPLAB X) should help to reverse engineering the mode switching logic from PIC mode to AVR mode.
Also for old PICKit 4/SNAP, it is said that you may still need MPLAB X to upgrade the FW. Ref: https://bloom.oscillate.io/docs/mplab-snap-avr-mode
The USB PID changes from PIC mode to AVR mode, so I believe FW change is involved.
A challenge with a brand new PICkit4 straight from the factory is that the FW it contains is so old that it doesn't have the AVR mode. That is why a FW upgrade is necessary the first time you want to set a new PICkit4 to AVR mode.
Since Microchip Studio 7.0.2594 both Studio and MPLAB X can change mode and update FW on PICkit4 and Snap.
A challenge with a brand new PICkit4 straight from the factory is that the FW it contains is so old that it doesn't have the AVR mode. That is why a FW upgrade is necessary the first time you want to set a new PICkit4 to AVR mode.
But could the version be detected, so Avrdude at least can tell the user that the firmware is outdated and can't be switched to AVR mode? And I'll assume the firmware flashed on the factory will eventually be updated so the PICkit4 and SNAP can support AVR mode out of the box?
I don't have a PICkit, so just guessing: If the USB PID changes (as written above), this probably means the default firmware is in some pre-CMSISDAP mode. AVRDUDE would thus not even be able to talk to the devuce at all, and tell the version. Once the firmware is updated, AVRDUDE can actually use it.
I just ordered the Microchip SNAP from Mouser Singapore. It is not as good as PICKit 4 but it is probably good enough for me.
A challenge with a brand new PICkit4 straight from the factory is that the FW it contains is so old that it doesn't have the AVR mode. That is why a FW upgrade is necessary the first time you want to set a new PICkit4 to AVR mode.
Indeed.
Since Microchip Studio 7.0.2594 both Studio and MPLAB X can change mode and update FW on PICkit4 and Snap.
I used MPLAB X to upgrade the FW (with a PIC18F87J90 project, no target connected) and then Microchip Studio (no need to connect any target) to change to AVR mode.
I'm closing this issue because factory fresk PK4/SNAPs is running an ancient firmware that doesn't even has an AVR mode. If Microchip added such functionality to their Pymcuprog too (or similar) we could probably replicate it. But as of right now, this is not something that's planned to do.
@janegilruud told me that might look into this sometime, so I'll re-open this issue again so we don't forget about it.
@MCUdude and @janegilruud
Any plan to look at this issue again?
@xedbg gave me some hints earlier, but I have very little knowledge about the low-level workings of USB, so I couldn't really get any further. I'm not sure how to use hidapi to do an USB bulk write to endpoint 2 either.
When in PIC mode, the VID is Microchip, (PID depends on the tool):
- USB bulk write to EP2 with [CMD_MODE_SWITCH=0xF0, AVR_MODE=1]
- USB bulk write to EP2 with [CMD_SW_RST=0xED]
You will surely need some mystery delays thrown in, but the tool should reset in AVR mode.
When in AVR mode, the VID is Atmel:
- HID packet: [HOUSEKEEPING protocol, CMD_FW_UPGRADE, IMAGE_SELECT_KEY=0x6A6D7000 | PIC_MODE=0]
https://github.com/microchip-pic-avr-tools/pyedbglib/blob/main/pyedbglib/protocols/housekeepingprotocol.py#L104
Again, some mystery delays are required.
There are some serial EEPROM writes which need to be done for each of these – the image-selector is stored there, and will be picked up at boot time.
@MCUdude
hidapi does not deal with bulk transfer as HID device only supports Control Transfer and Interrupt Transfer. And it does not talk in terms of Endpoints, rather using HID report.
libusb does support bulk transfer and talks using Endpoint. But it does not support HID devices under macOS.
You can dump the HID Report Descriptor under macOS using hidapi hidtest application or mac-hid-dump. https://github.com/libusb/hidapi/tree/master/hidtest https://github.com/todbot/mac-hid-dump
Then you can parse the descriptor using online parser here. https://eleccelerator.com/usbdescreqparser/
macOS USB Prober can do this as well and directly give you the parsed HID report descriptor.
PICKit 4 AVR Mode USB info
So we can see EP2 is the Interrup Out endpoint for the HID interface (the CMSIS-DAP interface).
mcuee@UbuntuSwift3:~$ lsusb -vvv -d 03eb:2177
Bus 003 Device 007: ID 03eb:2177 Atmel Corp.
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 239 Miscellaneous Device
bDeviceSubClass 2
bDeviceProtocol 1 Interface Association
bMaxPacketSize0 64
idVendor 0x03eb Atmel Corp.
idProduct 0x2177
bcdDevice 1.00
iManufacturer 1 Microchip Technology Incorporated
iProduct 2 MPLAB PICkit 4 CMSIS-DAP
iSerial 3 BURxxxxxxxxx
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 0x006b
bNumInterfaces 3
bConfigurationValue 1
iConfiguration 0
bmAttributes 0x80
(Bus Powered)
MaxPower 500mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 3 Human Interface Device
bInterfaceSubClass 0
bInterfaceProtocol 0
iInterface 0
HID Device Descriptor:
bLength 9
bDescriptorType 33
bcdHID 1.11
bCountryCode 0 Not supported
bNumDescriptors 1
bDescriptorType 34 Report
wDescriptorLength 35
Report Descriptors:
** UNAVAILABLE **
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x02 EP 2 OUT
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 1
Interface Association:
bLength 8
bDescriptorType 11
bFirstInterface 1
bInterfaceCount 2
bFunctionClass 2 Communications
bFunctionSubClass 2 Abstract (modem)
bFunctionProtocol 0
iFunction 5 PICkit 4 Virtual COM Port
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 2 Communications
bInterfaceSubClass 2 Abstract (modem)
bInterfaceProtocol 0
iInterface 0
CDC Header:
bcdCDC 1.10
CDC ACM:
bmCapabilities 0x02
line coding and serial state
CDC Union:
bMasterInterface 1
bSlaveInterface 2
CDC Call Management:
bmCapabilities 0x03
call management
use DataInterface
bDataInterface 2
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x84 EP 4 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 16
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 2
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 10 CDC Data
bInterfaceSubClass 0
bInterfaceProtocol 0
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x83 EP 3 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x05 EP 5 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 0
Device Qualifier (for other device speed):
bLength 10
bDescriptorType 6
bcdUSB 2.00
bDeviceClass 239 Miscellaneous Device
bDeviceSubClass 2
bDeviceProtocol 1 Interface Association
bMaxPacketSize0 64
bNumConfigurations 1
can't get debug descriptor: Resource temporarily unavailable
Device Status: 0x0000
(Bus Powered)
hidtest outpit info for PICKit 4 in AVR mode.
We can see if has no report ID ( so you use 0 as the fake report ID when using HIDAPI to talk to the device)
Input Report: 64 bytes Output Report: 64 bytes Feature Report: 4 Bytes
Device Found
type: 03eb 2177
path: /dev/hidraw3
serial_number: BURxxxxxxxxxx
Manufacturer: Microchip Technology Incorporated
Product: MPLAB PICkit 4 CMSIS-DAP
Release: 100
Interface: 0
Usage (page): 0x1 (0xff00)
Bus type: 1 (USB)
Report Descriptor: (35 bytes)
0x06, 0x00, 0xff, 0x09, 0x01, 0xa1, 0x01, 0x15, 0x00, 0x26,
0xff, 0x00, 0x75, 0x08, 0x96, 0x40, 0x00, 0x09, 0x01, 0x81,
0x02, 0x96, 0x40, 0x00, 0x09, 0x01, 0x91, 0x02, 0x95, 0x04,
0x09, 0x01, 0xb1, 0x02, 0xc0,
HID Parser output
0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00)
0x09, 0x01, // Usage (0x01)
0xA1, 0x01, // Collection (Application)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x75, 0x08, // Report Size (8)
0x96, 0x40, 0x00, // Report Count (64)
0x09, 0x01, // Usage (0x01)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x96, 0x40, 0x00, // Report Count (64)
0x09, 0x01, // Usage (0x01)
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x95, 0x04, // Report Count (4)
0x09, 0x01, // Usage (0x01)
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0xC0, // End Collection
// 35 bytes
@MCUdude
You can do the same for PICKIt 4 PIC mode. I am lazy to switch it back to PIC mode as I do not usually use MPLAB X or Microchip Studio myself.
I should be able to help you to convert the following into hidapi function with some reverse engineering.
When in PIC mode, the VID is Microchip, (PID depends on the tool):
- USB interrupt write to EP2 with [CMD_MODE_SWITCH=0xF0, AVR_MODE=1]
- USB interrupt write to EP2 with [CMD_SW_RST=0xED]
You will surely need some mystery delays thrown in, but the tool should reset in AVR mode.
And actually we can use hidapitester first to see how it works. I use the tool extensively for testing of HIDAPI. https://github.com/todbot/hidapitester
Apparently, the SNAP/PICkit4 won't be switched between PIC and AVR mode anymore, it will always stay in PIC mode when used with MPLAB.
https://www.avrfreaks.net/s/topic/a5CV400000004QDMAY/t393324?comment=P-2935548
@xedbg does this mean that "AVR mode" will be removed from the SNAP/PICkit4, and thus break Avrdude support?
Regardless, we should try to figure out how to switch modes, because this may be impossible to do if MPLAB doesn't do this anymore.
Apparently, the SNAP/PICkit4 won't be switched between PIC and AVR mode anymore, it will always stay in PIC mode when used with MPLAB.
https://www.avrfreaks.net/s/topic/a5CV400000004QDMAY/t393324?comment=P-2935548
Hmm, that is interesting to know.
If that is the case, probably the ultimate solution is to follow MPLAB and use the PIC mode in avrdude.
If that is the case, probably the ultimate solution is to follow MPLAB and use the PIC mode in avrdude.
Except that we don't know the "PIC mode" protocol. Just like we can't currently support PICkit5 because it has no AVR mode. I suspect this is what they're doing with the PICkit4/SNAP as well. All we can do at this moment is to add the switching functionality and hope they don't get rid of the dedicated AVR mode.
@mcuee you mentioned earlier that you could look into how the switch back and forth can be done using hidapitester. Would be great if you could do this, sometime, so we could implement this once and for all.
I have been able to use libusb directly to switch a PICkit4 and a SNAP from PIC mode to AVR mode. Switching back to PIC mode again is done using the EDBG protocol, so this should be straightforward. Now what we need to do is to properly implement this in the Avrdude source code:
libusb_example.c
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <usb.h>
#define VENDOR_ID 0x4d8 // Microchip VID
#define PRODUCT_ID 0x9018 // PIC mode SNAP PID
#define INTERFACE_NUMBER 0 // Replace with your device's interface number
#define ENDPOINT 0x02 // EP2 endpoint address
#define TIMEOUT 1000 // Timeout in milliseconds
int main() {
struct usb_dev_handle *dev_handle = NULL;
// Initialize libusb-0.1
usb_init();
usb_find_busses();
usb_find_devices();
// Open USB device
struct usb_bus *bus;
for (bus = usb_get_busses(); bus; bus = bus->next) {
struct usb_device *dev;
for (dev = bus->devices; dev; dev = dev->next) {
if (dev->descriptor.idVendor == VENDOR_ID && dev->descriptor.idProduct == PRODUCT_ID) {
dev_handle = usb_open(dev);
break;
}
}
if (dev_handle) break;
}
if (!dev_handle) {
fprintf(stderr, "Error opening device\n");
return 1;
}
// Claim interface
if (usb_claim_interface(dev_handle, INTERFACE_NUMBER) < 0) {
fprintf(stderr, "Error claiming interface\n");
usb_close(dev_handle);
return 1;
}
// Perform bulk write
const char data[] = {0xF0, 1};
int result = usb_bulk_write(dev_handle, ENDPOINT, data, sizeof(data), TIMEOUT);
if (result >= 0) {
printf("Bulk transfer successful. Transferred: %d bytes\n", result);
} else {
fprintf(stderr, "Error during bulk transfer: %s\n", usb_strerror());
}
// Mandatory delay
usleep(250*1000);
const char data2[] = {0xed};
result = usb_bulk_write(dev_handle, ENDPOINT, data2, sizeof(data2), TIMEOUT);
if (result >= 0) {
printf("Bulk transfer successful. Transferred: %d bytes\n", result);
} else {
fprintf(stderr, "Error during bulk transfer: %s\n", usb_strerror());
}
// Release interface and close device
usb_release_interface(dev_handle, INTERFACE_NUMBER);
usb_close(dev_handle);
return 0;
}
Makefile:
CC = gcc
CFLAGS = -Wall -I/usr/local/include/libusb-1.0
LDFLAGS = -L/usr/local/lib -lusb
TARGET = libusb_example
SRC = libusb_example.c
all: $(TARGET)
$(TARGET): $(SRC)
$(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
clean:
rm -f $(TARGET)
@MCUdude
It is great that you can switch the PICkit 4 and SNAP from PIC mode to AVR mode using a simple libusb application.
Have you been able to switch from AVR mode back to PIC mode?
One way is to ship this as a separate utility along with avrdude without integrating into avrdude, if it is a bit difficult to integrate into existing avrdude source codes.
@MCUdude
I'd like to give your libusb codes a test. My PICKit 4 is under AVR mode now. Just wondering how I can get it back to PIC mode to test your libusb codes. Thanks.
I have MPLAB X IDE 6.15 installed on my Windows 11 laptop.
Create a project in MPLAB that uses a PIC. When you try to build and upload, it will ask you to select a tool in a drop-down menu, and then to will switch it back to PIC mode. I had to install XC8 for PIC just for this...
Create a project in MPLAB that uses a PIC. When you try to build and upload, it will ask you to select a tool in a drop-down menu, and then to will switch it back to PIC mode. I had to install XC8 for PIC just for this...
Somehow I can not switch my PICkit 4 to PIC mode with an existing project using PIC18F87J50. I will try different projects later.
BTW, no issues building the code under MSYS2 mingw64 with minor modification of the Makefile.
$ cat Makefile
CC = gcc
CFLAGS = -Wall -I/mingw64/include/libusb-1.0 -I/mingw64/include/libusb-compat
LDFLAGS = -L/mingw64/lib -lusb
TARGET = libusb_example
SRC = libusb_example.c
all: $(TARGET)
$(TARGET): $(SRC)
$(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
clean:
rm -f $(TARGET)
$ make
gcc -Wall -I/mingw64/include/libusb-1.0 -I/mingw64/include/libusb-compat libusb_example.c -o libusb_example -L/mingw64/lib -lusb
$ ldd libusb_example.exe
ntdll.dll => /c/WINDOWS/SYSTEM32/ntdll.dll (0x7ff88d4d0000)
KERNEL32.DLL => /c/WINDOWS/System32/KERNEL32.DLL (0x7ff88c010000)
KERNELBASE.dll => /c/WINDOWS/System32/KERNELBASE.dll (0x7ff88ad20000)
msvcrt.dll => /c/WINDOWS/System32/msvcrt.dll (0x7ff88d0f0000)
libusb-0-1-4.dll => /mingw64/bin/libusb-0-1-4.dll (0x7ff8742c0000)
libusb-1.0.dll => /mingw64/bin/libusb-1.0.dll (0x7ff873760000)
Using the project file provided by @MCUdude, I think I have switched my PICKit 4 to PIC mode. But there are some issues with firmware updating under MPLAB X IDE 6.15.
Initially I have more problems but that was due to the use of WinUSB driver instead of USB HID driver for the AVR mode.
*****************************************************
Connecting to MPLAB PICkit 4
Currently loaded versions:
Application version...........00.07.28
Boot version..................01.00.00
PCB version...................4
Script version................00.05.85
Script build number...........d33d758f73
Tool pack version ............2.1.1763
Updating firmware application...
Reception on endpoint 129 failed (err = -10031)
@MCUdude
I think your libusb application works fine. Need to change to use PICKit 4 PID which is 0x9012.
MINGW64 /c/work/avr/avrdude_test/avr_pic_mode_switching
$ ./libusb_example_pickit4.exe
Bulk transfer successful. Transferred: 2 bytes
Bulk transfer successful. Transferred: 1 bytes
PR #1596 works well for mode swtiching, either from PIC mode to AVR mode, or from AVR mode to PIC mode.
PS> .\avrdude_pr1596 -C .\avrdude_pr1596.conf -c pickit4 -p m32a
avrdude_pr1596: AVR device initialized and ready to accept instructions
avrdude_pr1596: device signature = 0x1e9502 (probably m32a)
avrdude_pr1596 done. Thank you.
PS> .\avrdude_pr1596 -C .\avrdude_pr1596.conf -c pickit4 -p m32a -U flash:v:m32a_blink_read.hex:i
avrdude_pr1596: AVR device initialized and ready to accept instructions
avrdude_pr1596: device signature = 0x1e9502 (probably m32a)
avrdude_pr1596: processing -U flash:v:m32a_blink_read.hex:i
avrdude_pr1596: verifying flash memory against m32a_blink_read.hex
Reading | ################################################## | 100% 0.12 s
avrdude_pr1596: 526 bytes of flash verified
avrdude_pr1596 done. Thank you.
PS> .\avrdude_pr1596 -C .\avrdude_pr1596.conf -c pickit4 -p m32a
avrdude_pr1596: AVR device initialized and ready to accept instructions
avrdude_pr1596: device signature = 0x1e9502 (probably m32a)
avrdude_pr1596 done. Thank you.
PS> .\avrdude_pr1596 -C .\avrdude_pr1596.conf -c pickit4 -p m32a -xmode=pic
switching to PIC mode
PIC mode switch successful
avrdude_pr1596 error: unable to open port usb for programmer pickit4
avrdude_pr1596 done. Thank you.
PS> .\avrdude_pr1596 -C .\avrdude_pr1596.conf -c pickit4 -p m32a
avrdude_pr1596 error: PICkit4 in PIC mode detected.
use -xmode=avr to enter AVR mode
avrdude_pr1596 error: unable to open port usb for programmer pickit4
avrdude_pr1596 done. Thank you.
PS> .\avrdude_pr1596 -C .\avrdude_pr1596.conf -c pickit4 -p m32a -xmode=avr
avrdude_pr1596 error: PICkit4 in PIC mode detected.
switching to AVR mode
please re-run Avrdude
avrdude_pr1596 error: unable to open port usb for programmer pickit4
avrdude_pr1596 done. Thank you.
PS> .\avrdude_pr1596 -C .\avrdude_pr1596.conf -c pickit4 -p m32a
avrdude_pr1596: AVR device initialized and ready to accept instructions
avrdude_pr1596: device signature = 0x1e9502 (probably m32a)
avrdude_pr1596 done. Thank you.
PS> .\avrdude_pr1596 -C .\avrdude_pr1596.conf -c pickit4 -p m32a -U flash:v:m32a_blink_read.hex:i
avrdude_pr1596: AVR device initialized and ready to accept instructions
avrdude_pr1596: device signature = 0x1e9502 (probably m32a)
avrdude_pr1596: processing -U flash:v:m32a_blink_read.hex:i
avrdude_pr1596: verifying flash memory against m32a_blink_read.hex
Reading | ################################################## | 100% 0.11 s
avrdude_pr1596: 526 bytes of flash verified
avrdude_pr1596 done. Thank you.
Resolved by #1596
So, I see this issue is closed but it seems to not be working for me. I grabbed the current code and built it and it takes the argument, says it's worked, but when I run avrdude again to program the chip, it says the SNAP is still in pic mode.
avrdude: Version 7.3-20240229 (34366a6b) Running on Linux, Debian Testing.
Can you post the entire output when running Avrdude?
Sure.
dab@malabar> make switch
/home/dab/src/avrdude/build_linux/src/avrdude -c snap_pdi -Pusb -xmode=avr
avrdude error: MPLAB SNAP in PIC mode detected
switching to AVR mode
please run Avrdude again to continue the session
dab@malabar> make program
/home/dab/src/avrdude/build_linux/src/avrdude -p atxmega8e5 -c snap_pdi -U flash:w:main.hex
avrdude error: MPLAB SNAP in PIC mode detected
to switch into AVR mode try
avrdude -csnap_pdi -patxmega8e5 -Pusb -xmode=avr
I don't know if there are different versions of the SNAP programmer but mine has header pins with a jumper block that seems to indicate it selects either PIC or AVR. It's in the AVR position but I've tried both and see no difference.
Oh, you have a new one! Didn't even know they existed in the wild... :| I think that jumper is simply selecting pull-ups (AVR) or pull-downs (PIC) and has nothing to do with the image itself.
It's a bit difficult to tell what the reason is. I have an early hardware version of the SNAP, so I don't have any PIC/AVR mode jumper.
I have not been able to switch to AVR mode if the SNAP are in recovery mode. It report as being in PIC bootloader mode, and won't switch to AVR mode. I used MPLAB X 6.20 to flash the most recent firmware SNAP firmware (1.10 (rel. 249)
according to Avrdude), and I'm able to switch back and fourth without problems.
EDIT: @xedbg beat me to it!
I bought it through DigiKey in the last month. I don't have MPLAB but I see there's a Linux version. I guess I'll go see about updating the firmware then.
Looks like I need more help. I have mplab running but can't find any place to update the SNAP firmware. I've looked around both ide and ipe and it looks like it's just not there, despite what the documentation I can find says.
You need to create a new project, and select an AVR as the target MCU. When you try to upload the compiled code, MPLAB should update the firmware.
That seems excessively complicated. But I tried that and it didn't work. It would just hang trying to upload the image to the processor, never said anything about the firmware for the SNAP itself. Having seen the bit in the documentation about resetting the SNAP to factory settings, I tried that. Now the 'active' light is no longer lit and it doesn't respond at all. I think I messed it up good. I guess I'll try calling Microchip support tomorrow.
That seems excessively complicated
Indeed it is! I have a PICkit4 as well, and I had to force it into recovery mode to update its firmware. On my computer, I had this problem where if I used an older version of MPLAB X, it would flash an older firmware version, while if I used the latest MPLAB X, it wouldn't show up at all, because the firmware version was too old. Go figure... IIRC, I had to install MPLAB X 6.15 to flash the firmware that allowed 6.20 to recognize it.
A dedicated, cross-platform CLI program that could flash a Microchip/Atmel programmer with a user-specified binary would be a desirable solution. When I finally got my PICkit4 running the latest firmware, I had four or five separate MPLAB X versions installed on my computer simultaneously, occupying tons of gigabytes...
But MPLAB X is what Microchip wants us to use.
Woo hoo! It's working. When I did the Emergency Boot Firmware Recovery yesterday, it stopped working even more. It couldn't find the SNAP to download the firmware. I tried it again this morning before contacting tech support and this time it worked. Not only did it bring the SNAP back, but it must have upgraded the firmware (don't know what version it was before but it's now 1.11 (rel. 20)) because avrdude -xmode=avr now works and sticks. More than that, the board I was trying to program (a board I built so I was also testing that I got the whole PDI interface right) is now sitting there blinking its LED. I'm a happy programmer this morning. Thanks for your help and pointers to what I needed.
Thanks for the update @dabridgham . That emergency recovery is a really hard reset, putting the Snap back to a SAM-BA serial bootloader. I have also noticed it being somewhat fragile (but hopefully you should not have to do this often).
Brand new PICkit4 and MPLAB SNAP programmers are running in "PIC mode" by default, and can't program AVRs unless you download MPLAB X, create a project with an AVR, connect your programmer and then attempt to connect to the target MCU. It would be very convenient if Avrdude could detect a PICkit4 or a SNAP in PIC mode, and set it to AVR mode instead of using MPLAB X.
From the discussion in #1015:
avrdude: Detected PICkit4 programmer in PIC mode. Do you want to switch to AVR mode? (Y/n) Y avrdude: PICkit4 programmer switched to AVR mode avrdude: Please reconnect the programmer for the changes to take effect
avrdude done. Thank you.