arduino / arduino-cli

Arduino command line tool
https://arduino.github.io/arduino-cli/latest/
GNU General Public License v3.0
4.24k stars 372 forks source link

Option to specify programmer USB Bus and Device numbers #770

Open dbhaig opened 4 years ago

dbhaig commented 4 years ago

Feature Request

Current behavior

First of all, kudos to the developers for adding the burn-bootloader command!

I'm using a USBasp programmer and it works great.

It would be very handy if I could use more than one USBasp programmer simultaneously.

auduino-cli does not appear to support specifying programmer USB Bus and Device addressing.

Expected behavior

Options to specify a programmer using the USB Bus and Device numbers, e.g.:

lsusb ... Bus 001 Device 122: ID 16c0:05dc Van Ooijen Technische Informatica shared ID for use with libusb Bus 003 Device 036: ID 16c0:05dc Van Ooijen Technische Informatica shared ID for use with libusb ...

arduino-cli burn-bootloader -b arduino:avr:leonardo -P usbasp:001:122 -t -v arduino-cli burn-bootloader -b arduino:avr:leonardo -P usbasp:003:036 -t -v

Environment

Additional context

I have no idea how difficult this request would be to implement.

Thank you for your consideration.

matthijskooijman commented 4 years ago

This would indeed be useful to have, but probably requires some changes to the programmer/tool specifications.

As for adding these as part of the -P programmer option, that does not seem like the best approach. Conceptually, such an USB identifier would replace the -p port option (e.g. some existing programmers select between multiple connected programmers based on the serial port). So maybe the -p option could be extended to accept something like usb:001:122 (e.g. use a prefix to indicate the type of "port" to pass.

Finally, we should consider how such a USB device should be specified. Apparently the usbasp tools on Linux need a busnumber + device number (which I think might be Windows-specific), but for example dfu-util (on Windows and Linux) uses a USB path specification (bus number, dash, and dot-separated hub port indexes, e.g. 1-1.5.4.6).

One one hand, you could say arduino-cli does not need to know about this, it can just pass a "port" variable to the tools defined in programmers.txt / platform.txt, but it might be interesting if arduino-cli can actually detect attached programmers and suggest the needed commandlines etc. Also, at least on the Java IDE, the serial port is always* set (usually to the serial port of the device itself, not the programmer), so if a tool like usbasp would just use the port variable hoping that it contains an USB device identifier, it would likely just get a serial port on the Java IDE.

ubidefeo commented 4 years ago

@matthijskooijman in avrdude you specify -PUSB for a device on a USB port and programmers.txt maps VID:PID to use (I'm still bummed by -p being the port and not the programmer :( ) I think adding a path to specify a programmer doesn't fall too far from specifying which serial port a board is attached to in order to target multiple instances of the same board to the same machine. We need to think about this in a smart way, adding your comment to our next meeting bullets, thank you for the inspiration :)

matthijskooijman commented 4 years ago

in avrdude you specify -PUSB for a device on a USB port and programmers.txt maps VID:PID to use

I actually think the vid-pid to use is hardcoded inside avrdude, you need not specify it, right?

You can indeed use -Pusb to let avrude just pick the first available programmer with the right vidpid (based on the the programmer selected).

Looking at the avrude manpage, for some programmers, it seems to distinguish between multiple of the same type of programmers, you will have to specify the device's serial number:

               For the JTAG ICE mkII and JTAGICE3, if avrdude has been configured with libusb support, port can alternatively be specified as
              usb[:serialno].  This will cause avrdude to search the programmer on USB.  If 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.

Other devices apparently indeed use the usb device number:

              For the USBtinyISP, which is a simplicistic device not implementing serial numbers, multiple devices can be distinguished by their loca‐
              tion in the USB hierarchy.  See the the respective Troubleshooting entry in the detailed documentation for examples.

And from [Troubleshooting]():

Problem: Multiple USBasp or USBtinyISP programmers connected simultaneously are not found.

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 -P usb option, similar to adding a serial number on other USB-based programmers.

The actual naming convention for the bus and device names is operating-system dependant; AVRDUDE will print out what it found on the bus when running it with (at least) one -v option. By specifying a string that cannot match any existing device (for example, -P usb:xxx), the scan will list all possible candidate devices found on the bus.

Examples:

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)

So maybe it would be good to allow selecting an USB device in some way, and then exporting the usb ids in multiple properties, e.g. programmer.serial=1234, programmer.usb_bus=003, programmer.usb_device=025, programmer.usb_port_path=1-1.5.4.6 etc. Then the programmers.txt can use whatever of these properties is appropriate for the programmer to build the correct commandline. As for how to select the USB device to use, in a GUI a dropdown would be appropriate. On the commandline, it would be nice if multiple of these methods could be supported (e.g. you can pass -p usbserial:123 or -p usbnum:003:025 and arduino-cli could identify the device from that and then fill all relevant properties). You could then even specify a serial port (-p /dev/ttyACM0) and then have all USB properties derived from that.

Also, I realized that a lot of this is not really specific to programmers: There are also boards where a normal (bootloader-style) upload does not happen through a serial port, but through a native USB protocol (e.g. through DFU or some HID upload like I tihnk Teensy uses). I'm not sure if there's any way to distinguish between multiple such board connected during upload (I think not), but I think the same approach could be used here.

ubidefeo commented 4 years ago

hi @matthijskooijman sorry for the late reply but returned from the holidays I had a ton on my plate and wanted to take the right time to read through issues of interest :)

I actually think the vid-pid to use is hardcoded inside avrdude, you need not specify it, right?

correct in a way, they are listed in avrdude.conf which can be extended via an .avrduderc in the home folder to add other programmers or extend existing ones

Other devices apparently indeed use the usb device number:

So does Teensy, as far as I could figure out by playing with the command line tools installed by TeensyDuino inside the Java IDE. I like this approach a lot, especially because it gets around to finding devices which are configured as HiD peripherals.

On the commandline, it would be nice if multiple of these methods could be supported (e.g. you can pass -p usbserial:123 or -p usbnum:003:025 and arduino-cli could identify the device from that and then fill all relevant properties).

definitely worth looking into

You could then even specify a serial port (-p /dev/ttyACM0) and then have all USB properties derived from that.

As I pointed out above, if a device is configured as an HiD peripheral you won't have a U(S)ART available, and this wouldn't work

As always I thank you for your valuable input 🙏

matthijskooijman commented 4 years ago

As I pointed out above, if a device is configured as an HiD peripheral you won't have a U(S)ART available, and this wouldn't work

Yeah, I meant that if a UART is available, you can specify that and let arduino-cli translate that into the appropriate USB identifiers. If a board has no UART, then of course you will have to specify the USB ids directly.

umbynos commented 1 year ago

Hi @dbhaig, at the moment, it could be created a pluggable discovery that does the discovery of the programmer/board, and it gives it an address to that object. Once this exists, the address could be passed to the upload tool to perform the upload. In theory, this does not require any modification to the cli.