Unable to Specify Upload Port for Teensy Loader Using PlatformIO

Status
Not open for further replies.
Hi. I am attempting to upload firmware to multiple Teensy 4.0 boards, one by one from the command line using PlatformIO. I have 8 Teensy 4.0 boards connected to my Linux desktop with ports /dev/ttyACM0 - /dev/ttyACM7. When I run the command:
Code:
pio run -e teensy40 --target upload --upload-port /dev/ttyACM1
It seems to upload to the Teensy board on port /dev/ttyACM0 instead of /dev/ttyACM1. This happens whether I use teensy-gui or teensy-cli. When using teensy-gui, I get this message:
Code:
Found 8 Teensy boards, but using auto-search to find board for upload.
Please use Tools > Ports(Teensy) to select the specific board.
Which makes me think it is just ignoring the --upload-port option.

I do not see any option in the teensy_loader_cli for specifying the upload port. Is there any other way to upload firmware to multiple Teensy boards without having to select them one by one in the Arduino GUI? Thanks!
 
Which makes me think it is just ignoring the --upload-port option.

That would be my guess, that it's ignoring --upload-port.


Is there any other way to upload firmware to multiple Teensy boards without having to select them one by one in the Arduino GUI? Thanks!

Yes, there are actually 2 other ways.

You could set the baud rate to 134 on the serial device, perhaps with "stty". Setting 134 baud tells Teensy to go into programming mode. Then run the loader and it will find the one which is already in programming mode.

Or you could run "teensy_post_compile". To see how, turn on verbose output while uploading in Arduino's File > Preferences. This method works even when Teensy is in non-Serial modes like MIDI or Audio. Then do an upload and watch the command Arduino runs. The tricky part is the USB port is specified by its Linux sysfs name, not the serial port name. You can get a list of connected devices by running "teensy_ports -L". Or you can write code with libudev or perhaps other ways Linux makes udev & sysfs info available.
 
Setting the baud rate to 134 of each port before uploading seems to work. Like you suggested I used the stty command:
Code:
stty -F /dev/ttyACM1 134
It is difficult to tell if it is working properly since I do not see any output from the teensy loader about which port it is using. I cannot tell from the command line if it is uploading to the same port over and over again or if it is properly changing ports. Watching the red leds on the Teensy boards and examining the uploaded firmware afterwards makes me think it is working though.

If the teensy loader is ignoring the PlatformIO --upload-port option, is that an issue with the teensy loader or with PlatformIO? Should I notify PlatformIO or is this something that may get fixed in the teensy loader someday? Thanks again for you help!
 
If the teensy loader is ignoring the PlatformIO --upload-port option, is that an issue with the teensy loader or with PlatformIO?

I'm reluctant to comment too deeply about PlatformIO, since I don't personally use it. But if you try that other approach with teensy_post_compile and teensy_ports, I believe you can see we're using a very different convention to specify ports. The port names Teensy's tools expect are based on the physical USB port on your computer (and its hubs). PlatformIO seems to be using the serial port names as defined by the operating system.

In Teensyduino 1.41 and older, we used to use the serial port names. The main downside to the serial port names is Teensy supports many USB modes where there is no serial port at all. Teensy's bootloader mode also uses no serial port, it's 100% HID protocol. In those old versions, the software was forced to resort to guessing if you had more than 1 Teensy connected, or if you changed the Tools > USB Type setting in Arduino. A secondary problem happens in Windows and Linux, where a different COM port or serial device name is sometimes assigned by the operating system. Linux is particularly problematic if you have multiple boards and you switch USB Type settings, because it reassigns the serial port name each time Teensy reboots. If some non-Arduino software holds the port open, things get even more mixed up on Linux.

Starting with Teensyduino 1.42, we switched to using port names which represent the USB controller, chain of USB hubs, and the physical USB port. This solves all of the problems I just mentioned. If Linux assigns a different port name, we still access the same physical device because we're now finding it based on the Linux sysfs name which represents the physical location. Likewise on MacOS and Windows, we're using names which encode the physical location, so we can have a highly consistent way on all 3 systems of referencing the actual Teensy you selected, even as is changes from Serial to HID in bootloader mode to perhaps something like MIDI if you upload a program which isn't USB serial.

This is possible on Arduino because of a feature called Pluggable Discovery, which actually began as code I developed to enable 1.42's physical ports. That code was contributed to Arduino. Cristian Maglie (Arduino's lead developer at the time) rewrote much of the code, but the concept is the same. A platform like Teensy can provide its own tools to discover which devices are connected, and the tools to actually use the devices. In this mode, the Arduino IDE doesn't care what the port names actually mean. It just uses the Teensy-provided tools to communicate, referencing those arbitrary port names it received from the discovery tool.

Again, I'm not an expert on PlatformIO, but my limited understanding is it does not yet have anything nearly as flexible as Arduino's Pluggable Discovery. Every indication I see is PlatformIO requires port names which actually are COM ports or serial devices. That's a poor fit with Teensy since we use HID protocol in bootloader mode and support many non-Serial protocols (can those even be used at all from PlatformIO??) It's also a pretty awkward interface between PlatformIO which expects port names to be serial devices and Teensy's tools which revolve around very different port names which specify physical USB ports.

Until PlatformIO gets a more flexible way like Pluggable Discovery, I do not believe there is any easy solution that will give a very reliable way. The cold hard reality is the old "everything must be a serial port" paradigm has never worked well for Teensy's use of many different USB protocols. That's why so much work went into Teensyduino 1.42 and contributing Pluggable Discover to Arduino.

Even now with Teensyduino 1.53, the tools for Teensy still support a long legacy of the guesswork approach we always had to use before the switch to physical port names in Teensyduino 1.42. It's very unlikely I'll ever remove all that ancient code from the tools, even though we don't really use it anymore, because other systems are still based on OS serial ports. But the caveat is that "everything must be serial" approach just can't ever be reliably precise for hardware like Teensy which dynamically changes from Serial to HID to MIDI, Audio, and other stuff (and more protocols likely to come in the future).
 
FWIW, I was able to make platformio work with tycmd to be able to specify individual teensies for upload. From one of my platformio.ini files:

Code:
[env:teensylc]
framework = arduino
platform = teensy
board = teensylc
upload_command = tycmd upload -B $UPLOAD_PORT $SOURCE
build_flags = -DUSB_SERIAL_HID -DLAYOUT_US_ENGLISH
upload_port = 1732640-Teensy
 
I believe there is another way as well... At least I have been able to update two Teensy boards at the same time and same program using TyCommander.

There are several threads on it including: https://forum.pjrc.com/threads/27825-Teensy-Qt
And you can find it up at: https://koromix.dev/tytools

But again I don't use platformIO directly (or mostly at all).

I do use TyCommander to upload by having it install into our Arduino builds as well as builds within SublimeText.

Where I am not sure if it works with PlatformIO is at times I have played with PlatformIO sort of integrated into Sublime text using the Deviot plugin...

But before when I would do it, I would do a build, which would then launch TyCommander and if first time during session, it would show you the currently plugged in Teensy boards and allow you to choose which one. At this point it allowed you to select multiple boards and update each of the ones you selected... But it has been awhile since I did this.

There is a second way to choose multiple boards, but I don't remember all of the details, but probably in the instructions.
 
Interesting, thank you for the wonderful explanation and all of your great work. This is my first time using PlatformIO, so I do not know much about it yet either. I just wanted a way to compile and link some Arduino code and its dependencies from a command line and upload it to many identical Teensy boards. Do you have a recommendation on the best way to do that without using PlatformIO or the Arduino IDE? Perhaps with just a Makefile and something like the teensy command line loader? As I am typing this I see blackketter's reply, I had never heard of tycmd, but that looks super promising, thanks!
 
If it was Windows and not linux this works to run installed IDE/TeensyDuino from Commnad line :: github.com/Defragster/Tset

As KurtE notes it also uses TyCommander for multiple uploads.

It uses Windows Batch files ( .CMD ) - it 'seems' with edits it could run on Linux command line.
> Before it only did dir search for first .INO then pushed that into command line build , it was recently edited to store INO name when known and use that
> It populates that and other details onto command line to execute the build as the IDE does it. Capturing the build output as Paul noted in p#2

The core execution file in the sketch folder Compile.cmd is generated with TSET batch file that prompts for those items used in the IDE / Boards details to specify Teensy and other build settings.
 
Status
Not open for further replies.
Back
Top