Description
Describe the request
I use arduino-cli on Intel Linux to compile and upload sketches to my Arduino, which is an Adafruit Feather M4 CAN.
Usually, the feather comes up as /dev/ttyACM0. Sometimes it's /dev/ttyACM1.
My request is that I would like to deal with the port device name in a clear stable way.
I had been resolving this problem by putting this code in my arduino-cli bash wrapper script:
PORT=$(echo /dev/ttyACM?)
arduino-cli upload --port $PORT etc.
That has worked reliably for me. But I wanted to try making a udev rule for a /dev/feather_m4_can
with a symlink, so I could just say:
PORT=/dev/feather_m4_can
arduino-cli upload --port $PORT etc.
without ambiguity, in my scripts. I have not been able to make this work reliably.
I know that when I run arduino-cli upload, the udev system does several bind/unbind and add/remove operations on the usb device, and its ID wiggles between a normal 239a:80cd and a bootloader 239a:00cd.
When I run lsusb (in a loop) during an arduino-cli upload, it shows this:
Bus 001 Device 026: ID 239a:80cd Adafruit Feather M4 CAN
Bus 001 Device 027: ID 239a:00cd Adafruit Feather M4 CAN Express
Bus 001 Device 028: ID 239a:80cd Adafruit Feather M4 CAN
I wrote a new local udev rule
/etc/udev/rules.d/99-myfeatherm4.rules
that looks like this:
SUBSYSTEM=="tty", ATTRS{idVendor}=="239a", ATTRS{idProduct}=="80cd", SYMLINK+="feather_m4_can"
SUBSYSTEM=="tty", ATTRS{idVendor}=="239a", ATTRS{idProduct}=="00cd", SYMLINK+="feather_m4_can"
It makes a good-looking symlnk, but arduino-cli doesn't work with it.
$ ls -l /dev/ttyA* /dev/feather*
lrwxrwxrwx 1 root root 7 Feb 24 13:28 /dev/feather_m4_can -> ttyACM0
crw-rw---- 1 root dialout 166, 0 Feb 24 13:28 /dev/ttyACM0
$ ~/bin/arduino-cli_1.2.0 upload --port /dev/feather_m4_can --fqbn adafruit:samd:adafruit_feather_m4_can mysketch.ino --input-dir /home/me/lib/ardbin/mysketchdir
No device found on feather_m4_can
Failed uploading: uploading error: exit status 1
I know I can use:
PORT=$(echo /dev/ttyACM?)
or even
PORT=$(readlink -f /dev/feather_m4_can)
but I'd like to just use:
PORT=/dev/feather_m4_can
if possible.
Is my problem with my udev rule?
Or is it a problem with the way arduino-cli is treating the symlink?
(why does it work with /dev/ttyACM0 but not with the symlink?)
Is there a best simple way to specify the port?
Describe the current behavior
When I use my udev rule device name with a symlink to my feather, it fails.
(I keep my bin/arduino-cli versions with version number in the name, then I symlink bin/arduino-cli to the version I want)
$ ~/bin/arduino-cli_1.2.0 upload --port /dev/feather_m4_can --fqbn adafruit:samd:adafruit_feather_m4_can mysketch.ino --input-dir /home/me/lib/ardbin/mysketchdir
No device found on feather_m4_can
Failed uploading: uploading error: exit status 1
Arduino CLI version
latest 1.2.0, also earlier versions
Operating system
Linux
Operating system version
6.8.0-53-generic ubuntu
Additional context
No response
Issue checklist
- I searched for previous requests in the issue trackerI verified the feature was still missing when using the nightly buildMy request contains all necessary details
Activity
Ecophagy commentedon Feb 25, 2025
I attempted a similar thing with the same result - I have to use $(readlink -f <udev_name>). I believe it's because the underlying serial library is very strict about the port names it will accept. So I'm not sure it's something arduino-cli can fix by itself.
There was also some discussion about the issue here: arduino/Arduino#6776
atannen commentedon Feb 25, 2025
Thanks, Oliver. I had not seen that issue.
I was not aware of the port name regex filter.
I think that for my feather, arduino-cli calls bossac rather than avrdude, but the problem is the same.
I just wanted to understand what's going on and what other people do, to make sure I wasn't on the wrong track.
the driver identifies my feather in /dev/serial/by-id with a name that is unique per board:
usb-Adafruit_Feather_M4_CAN_<32-ascii-hex-digit-serial-number>-if00
that seems cumbersome for my needs.
I decided to hack my udev rule to look like this:
SUBSYSTEM=="tty", ATTRS{idVendor}=="239a", ATTRS{idProduct}=="80cd", SYMLINK+="ttyACM000"
SUBSYSTEM=="tty", ATTRS{idVendor}=="239a", ATTRS{idProduct}=="00cd", SYMLINK+="ttyACM000"
I don't think anyone else will generate /dev/ttyACM000, and it matches the regex filter.
It would be helpful if arduino-cli had a clearer error message when the device name does not match the regex filter.
cmaglie commentedon Mar 3, 2025
I think that the message
No device found on feather_m4_can
is coming frombossac
.Could you run the upload command with the
-v
flag and paste here the output?atannen commentedon Mar 3, 2025
Thank you, yes, Christian, it looks like the "failed" message is from bossac.
$ ls -l /dev/ttyA* /dev/fea*
lrwxrwxrwx 1 root root 7 Mar 3 11:01 /dev/feather_m4_can -> ttyACM0
crw-rw---- 1 root dialout 166, 0 Mar 3 11:05 /dev/ttyACM0
lrwxrwxrwx 1 root root 7 Mar 3 10:25 /dev/ttyACM000 -> ttyACM0
with /dev/feather_m4_can
$ arduino-cli upload --port /dev/feather_m4_can --fqbn adafruit:samd:adafruit_feather_m4_can myprog --input-dir /home/me/lib/ardbin/myprog
No device found on feather_m4_can
Failed uploading: uploading error: exit status 1
with /dev/feather_m4_can -v
$ arduino-cli upload -v --port /dev/feather_m4_can --fqbn adafruit:samd:adafruit_feather_m4_can myprog --input-dir /home/me/lib/ardbin/myprog
Waiting for upload port...
No upload port found, using /dev/feather_m4_can as fallback
"/home/me/.arduino15/packages/adafruit/tools/bossac/1.8.0-48-gb176eee/bossac" -i -d --port=feather_m4_can -U -i --offset=0x4000 -w -v "/home/me/lib/ardbin/myprog/myprog.ino.bin" -R
No device found on feather_m4_can
Set binary mode
Send auto-baud
Set binary mode
Failed uploading: uploading error: exit status 1
with /dev/ttyACM000 slinked to /dev/ttyACM0 arduino-cli upload works...
$ arduino-cli upload -v --port /dev/ttyACM000 --fqbn adafruit:samd:adafruit_feather_m4_can myprog --input-dir /home/me/lib/ardbin/myprog
Performing 1200-bps touch reset on serial port /dev/ttyACM000
Waiting for upload port...
Upload port found on /dev/ttyACM0
"/home/me/.arduino15/packages/adafruit/tools/bossac/1.8.0-48-gb176eee/bossac" -i -d --port=ttyACM0 -U -i --offset=0x4000 -w -v "/home/me/lib/ardbin/myprog/myprog.ino.bin" -R
Set binary mode
version()=v1.1 [Arduino:XYZ] Dec 1 2020 23:34:37
Connected at 921600 baud
readWord(addr=0)=0x2000d6a0
readWord(addr=0xe000ed00)=0x410fc241
readWord(addr=0x4)=0x575
readWord(addr=0x41002018)=0x61810002
etc...
oddly, I cut this bossac command from the upload output just above, and it doesn't work.
but this might not be relevant to my question.
"/home/me/.arduino15/packages/adafruit/tools/bossac/1.8.0-48-gb176eee/bossac" -i -d --port=ttyACM0 -U -i --offset=0x4000 -w -v "/home/me/lib/ardbin/myprog/myprog.ino.bin" -R
Set binary mode
Send auto-baud
Set binary mode
No device found on ttyACM0