Switch USB Dual/Triple to Single USB Serial from within Teensy 4.x?

rmac

Member
Hi all,

is it somehow possible to change from Triple/Dual USB Serial to Single USB Serial at startup/boot of Teensy 4.x?
In other words: is it possible to deactivate the second/third USB channel completely at "runtime"?

Background:
I would like to compile with active Dual USB Serial with the second USB channel for debug purposes, but only if a certain jumper is set.
If the jumper isn't set, the second USB serial should be deactivated immediately after startup so it is invisible in device manager.

Thx in advance
 
Building with DUAL USB would seem to take more space for buffers and code. But given a Jumper any code sending or receiving on that 2nd USB 'device port' could be prevented. The Host would see both ports, but the Teensy would simply ignore and not use the 2nd.

I've posted code long before and some months back where the Teensy on startup {before USB_INIT()}can alter the descriptor list presented to the USB Host - that may work here as well so that the Host can only see a single device port. However, that would not remove the 2nd Dual USB code form the build and any code referencing it would need to be made 'safe' (as above) if that works.
 
Serial1, Serial 2 and Serial3 are all UART devices, nothing to do with USB.

I know that, but it wasn't the question.


Building with DUAL USB would seem to take more space for buffers and code. But given a Jumper any code sending or receiving on that 2nd USB 'device port' could be prevented. The Host would see both ports, but the Teensy would simply ignore and not use the 2nd.

I've posted code long before and some months back where the Teensy on startup {before USB_INIT()}can alter the descriptor list presented to the USB Host - that may work here as well so that the Host can only see a single device port. However, that would not remove the 2nd Dual USB code form the build and any code referencing it would need to be made 'safe' (as above) if that works.

Thanks for the hint. I'll try to locate your code and check it out.
Well, the code overhead is not the problem. Most important is the (in-)visibility to the host.

Thank you
 
The short and simple answer is no, it's not possible to change the USB Type at runtime.

The long and complicated answer is also mostly no, but with explanation of the obstacles and what problems you would have to deal with if you overcame those obstacles.

The main obstacle is the way USB enumeration works. When the USB host (or a USB hub the host controls) detects connection of a new device, the host goes through a process called "enumeration" where it learns of the USB device's capabilities. The main reason you can't change the device (Teensy) USB Type at runtime is the USB host only does this enumeration process once, shortly after it detects the device has connected.

You could write code which turns off the USB port. After some time (should be 10ms by the USB spec, though some hubs might take longer) the host will detect Teensy has disconnected. To the host (your PC) it is the same as if the USB cable had been physically unplugged. This happens every time you upload new code. It certainly is possible to do under software control. But you can't make it "seamless". On your PC, the situation is the same as if you unplugged the hardware and then quickly plugged in different hardware.

Even just doing that won't be easy, because none of the code is designed and tested to do it. Turning off the USB hardware is involves just writing to a couple hardware registers. Modern systems should handle it well. Older versions of Windows could crash if you do this in the middle of a control transfer, which is the reason Teensy's USB code has a software timer. Re-initializing the USB hardware is also another path that never gets any testing, because it simply never happens.

If you do get the USB disconnect and reconnect working, the final obstacle is the software design is for just a single USB Type defined at compile time. All the code for every type exists, surrounded by #ifdef checks. You'll need to replace some of those with runtime checks rather than at compile time. The first part is just answering the requests for device descriptors differently at runtime. Then the USB host will try to communicate with the interfaces / endpoints you told it. That may actually be simpler if the 2 modes you want are similar like going from dual serial to triple serial. You could have have the triple serial code compiled and the USB host won't try to communicate with the 3rd serial interface if you told it only 2 exist. Obviously if you tried something more complex where the descriptors tell the host a very different set of endpoints / interfaces exist, then you'd need more runtime tests.

So that's the long and complicated answer. If you're willing to live with the required disconnect to change modes (Windows will assign different COM ports, user level programs which don't handle USB disconnect will need to restart, etc), and you can dive into the USB device code to make these sorts of structural changes, it could be done. But the disconnect behavior is a pretty big caveat. It won't ever be a seamless experience.
 
@defragster: Thanks a lot for this links. Initially I tried to find them by myself, but I didn't come that far.

@PaulStoffregen: Thank you for this detailed explanations. It clarified a lot of the internals.
For me the disconnect/restart cycle to change USB modes is absolutely okay because it is not used regularly but for debug purposes only.
The switch of modes/types will also be between single/dual/triple USB serial only, not between other interface types.

Again thanks so far
cheers
 
@rmac - good luck. As Paul notes this isn't trivial or tested or by design. It may work but takes some messing around in CORES to do any sort of hacking to facilitate.

Has UART Serial for debug been considered? A second Teensy 4.x on the Debug Robot and a second USB cable to that Teensy sharing GND and a UART Rx/TX serial# set of pins could 'ECHO' from the UART port bidirectionally through the 2nd Teensy to a PC for debug? UART Serial should work at 5 or 6 Mbps with short wires and be quite effective, and when unplugged would not be 'user accessible'. No idea what the robot looks like or access to pins on the Teensy ... but a jumper on Rx/Tx of the UART would give a loop in non-debug more and when Second debug Teensy were connected as indicated the 'ECHO' loop would be through a second Serial Monitor.
 
The current hardware design of my project, which started some years ago, looks like this:

Teensy 4.1 is the controller of a measurement device which controls a BLDC-motor via CAN and reads different sensor values (force, length, ...).
The measurement data is send to a connected PC, on which a evaluating software is running. As main (host) interface UART Serial1 with a FT232 driver is used and accessible through a USB jack.
Teensy's USB/Serial is not accessible by ordinary users outside the casing and only used for debugging and firmware updates by maintenance personnel.

In the now planned re-design I'd like to make it somewhat leaner and get rid of overhead components (FT232 among others). So I came up with the idea of utilizing the Dual Serial mode with the second channel
as main host interface. Hiding the debug/update "channel" from the normal user would be nice, but is not essential!

I'll take a look at the things you've posted and what Paul mentioned. If I don't get it in a reasonable amount of time, it's not really a big deal and I will find another way :)

Thanks again
 
Back
Top