Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Teensy3 usb triple serial #438

Merged
merged 10 commits into from
Feb 22, 2020

Conversation

geertu
Copy link
Contributor

@geertu geertu commented Feb 18, 2020

Add support for dual (USB_DUAL_SERIAL) and triple (USB_TRIPLE_SERIAL) serial port configurations, providing a composite USB device, comprised of two or three serial ports.
The second serial port is called usb_serial2 (C) or SerialA (C++).
The third serial port is called usb_serial3 (C) or SerialB (C++).

When processing CDC_SET_CONTROL_LINE_STATE and CDC_SET_LINE_CODING
requests, wIndex is ignored.  Hence if the CDC Status Interface is
enabled, these requests are always processed, even when not destined for
the actual serial status interface.

Fix this by adding a check to ensure that wIndex matches the CDC status
interface.

Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
  - usb_serial_class::readBytes() calls millis(), hence it should
    include "core_pins.h",
  - usb_serial_flush_callback() is a public function, but is not
    declared in the header file.

Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
When including "core_pins.h":

    teensy3/usb_dev.c: In function '_reboot_Teensyduino_':
    teensy3/usb_dev.c:899:1: warning: 'noreturn' function does return

Fix this by adding a call to __builtin_unreachable().

Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Include <usb_serial.h> instead of duplicating the needed forward
declarations.

Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Create a macro to emit all values for the various CDC descriptors, and
use it.  Note that this does not include the CDC Interface Association
Descriptor, as the latter is needed only for composite USB devices.

This will avoid duplication when adding support for multiple USB serial
interfaces.

Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Create a macro to emit all values for a CDC Interface Association
Descriptor, and use it.

This will avoid duplication when adding support for multiple USB serial
interfaces.

Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Extract core USB serial functionality in a new usb_serial_port C class,
to allow creating multiple USB serial instances without duplicating all
code.

The original API is retained by creating static inline functions and
preprocessor macros using the old names, which are wrappers around the
new usb_serial_port functions and data members.

Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Add preprocessor macros to control the naming of functions, structures
and classes, to ease the creation of multiple USB serial instances.
Name generation for each instance is controlled using the
USB_SERIAL_SUFFIX and SERIAL_CLASS_SUFFIX defines.

Move the preprocessor macro wrappers around the usb_serial_port data
members to usb_serial.h, as preprocessor macro names cannot be
parameterized.

Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Add support for a dual serial port configuration (USB_DUAL_SERIAL),
providing a composite USB device, comprised of two serial ports.
The second serial port is called usb_serial2 (C) or SerialA (C++).

Note that no dummy C++ class is created if USB_DISABLED is defined,
unlike for the first port.

This increases binary size by ca. 1.2 KiB (720 bytes for USB buffers).

Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Add support for a triple serial port configuration (USB_TRIPLE_SERIAL),
providing a composite USB device, comprised of three serial ports.
The third serial port is called usb_serial3 (C) or SerialB (C++).

Note that no dummy C++ class is created if USB_DISABLED is defined,
unlike for the first port.

This increases binary size by ca. 0.5 KiB (despite needing 720 more
bytes for USB buffers, as gcc-5.4.1 no longer decides to unroll a loop
over all endpoints in usb_isr()).

Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
@luni64
Copy link
Contributor

luni64 commented Feb 18, 2020

Wow, that might be extremely useful for debugging if you need Serial for normal communication to the PC.

I gave it a quick try, it compiles without issues and generates the second port (WIN10) which appears in the device manager.
Both ports can be opened with putty, and the normal Serial works as usual.
But, I can't use SerialB, SerialA or usb_serial2. It seems to be not defined. Do I need to change other defines besides changing -DUSB_SERIAL to -DUSB_DUAL_SERIAL to make this work?

Edit: TyCommander does not recognize a Teensy having two ports. So, reprogramming needs the button, but that can probably be fixed.

@geertu
Copy link
Contributor Author

geertu commented Feb 18, 2020

Changing -DUSB_SERIAL to -DUSB_DUAL_SERIAL should be sufficient.
After that, any of the following should work:
usb_serial2_putchar('x');
SerialA.write("hello\n\r");

TBH, I'm not using the Arduino environment, but C and Makefiles, so I may be missing a minor detail.
For reference, my full project on top of this is at https://github.com/geertu/teensy3-bcu2

@luni64
Copy link
Contributor

luni64 commented Feb 18, 2020

TBH, I'm not using the Arduino environment, but C and Makefiles, so I may be missing a minor detail.

So do I... Found it, was my fault I changed the define in the makefile but forgot to do the same change in the intellisense config. So, vsCode marked SerialA as not defined and I believed it. Silly me...

Everything runs out of the box, the only issue I see at the moment is the compatibility to the uploaders. Tried TyCommander which gets confused. I'll give teensy.exe a go later.

@luni64
Copy link
Contributor

luni64 commented Feb 18, 2020

Same with Teensy.exe, after resetting, it looses the board. Pressing the programming button works of course.

@PaulStoffregen PaulStoffregen merged commit 7502174 into PaulStoffregen:master Feb 22, 2020
@PaulStoffregen
Copy link
Owner

I really do appreciate that you've contributed this code back to the core library. But much the macro trickery appears to be incompatible with the Arduino IDE. I need to undo some of that work. Just wanted to let you know... it's not that I don't appreciate everything you've done here. This needs to work with the Arduino IDE (appears that was never tested). Just wanted to let you know why I have to undo parts of this.

@geertu
Copy link
Contributor Author

geertu commented Feb 24, 2020

I really do appreciate that you've contributed this code back to the core library. But much the macro trickery appears to be incompatible with the Arduino IDE. I need to undo some of that work. Just wanted to let you know... it's not that I don't appreciate everything you've done here. This needs to work with the Arduino IDE (appears that was never tested). Just wanted to let you know why I have to undo parts of this.

Np. What exactly is failing?
BTW, I'm a bit confused: according to GitHub, my pull request was successfully merged and closed, and I don't see any reverts?
Thanks!

@PaulStoffregen
Copy link
Owner

I've just pushed the reverts. This broke things very badly for building with the Arduino IDE.

I'm going through it now to manually part parts back in. But this sort of tricky preprocessor usage, while elegant, it utterly incompatible with the Arduino IDE. We just can't use it like this.

@geertu
Copy link
Contributor Author

geertu commented Feb 24, 2020

I've just pushed the reverts. This broke things very badly for building with the Arduino IDE.

I'm going through it now to manually part parts back in. But this sort of tricky preprocessor usage, while elegant, it utterly incompatible with the Arduino IDE. We just can't use it like this.

Thanks, I'll hope to have a closer look at the issues tomorrow.
My apologies, I should have verified with the Arduino IDE before.

@PaulStoffregen
Copy link
Owner

I'm working now to convert it to a large, not-nearly-so-pretty expansion of the macros, so it can build with Arduino. Should have it in a few hours...

@PaulStoffregen
Copy link
Owner

It's not pretty and it duplicates (triplicates) a lot of code, but compiles with Arduino IDE.
cd4c30f

@luni64
Copy link
Contributor

luni64 commented Feb 24, 2020

Great, do you plan to make Teensy.exe compatible to this?

@PaulStoffregen
Copy link
Owner

Yes, but I may release a first 1.52 beta before updating the tools to properly deal with these 2 new USB types.

@PaulStoffregen
Copy link
Owner

Fixing the code so there aren't compile errors was of course the most urgent thing. Can't start a beta with code that's not compiling in Arduino.

@luni64
Copy link
Contributor

luni64 commented Feb 24, 2020

Sure, just tested the new version with Win10 and Arduino 1.8.5. Works perfectly.

@geertu
Copy link
Contributor Author

geertu commented Feb 25, 2020

It's not pretty and it duplicates (triplicates) a lot of code, but compiles with Arduino IDE.
cd4c30f

Thanks, that looks pretty similar to what I had before introducing serial_port and the macros for deduplication.
I went over all changes, and it looks good to me. Except for a harmless port2/3 mixup (pull request sent ;-)

BTW, I can confirm commit 7f3222c ("Allow any of the Daul & Triple serial to request reboot") fixes automatic reboot for programming for me. Thanks!

@geertu
Copy link
Contributor Author

geertu commented Feb 25, 2020

Hi Paul,

I've just pushed the reverts. This broke things very badly for building with the Arduino IDE.
I'm going through it now to manually part parts back in. But this sort of tricky preprocessor usage, while elegant, it utterly incompatible with the Arduino IDE. We just can't use it like this.

Thanks, I'll hope to have a closer look at the issues tomorrow.
My apologies, I should have verified with the Arduino IDE before.

So I gave it a try in the Arduino IDE (replaced cores in installed teensyduino by this repo, and added dual/triple serial defs to teensy/avr/boards.txt).

It turns out the sole offender in my macros is
#define USB_SERIAL_SUFFIX /* none /
#define SERIAL_CLASS_SUFFIX /
none */
in teensy3/usb_serial.h. Changing to C++-style comments doesn't help.
Due to the use of the "-CC" option, the compiler doesn't discard comments, and converts all C++-style comments inside a macro to C-style comments :-( As plain Arduino also uses "-CC", removing this is not an option, I guess. Do you know the rationale behind using this option?
Replacing the offending lines by
#define USB_SERIAL_SUFFIX
#define SERIAL_CLASS_SUFFIX
makes it build for me.

However, I'm not 100% confident this fixes all issues. USB serial operation and programming from the Arduino IDE (arduino-1.8.10+teensyduino-1.48) seems to be very unreliable and unpredictable for me. Note that that is even the case when using a cores version from before you merged my branch, so these issues may be completely unrelated.

Thanks!

@PaulStoffregen
Copy link
Owner

PaulStoffregen commented Feb 26, 2020

I ported this to Teensy 4.0.

I'm going to make one more change before releasing a beta test. Arduino's naming convention seems to be SerialUSB. We already support SerialUSB as an alias for Serial (and I believe Arduino does too on their board where they are the same). So I'm going to go with SerialUSB1 and SerialUSB2 rather than SerialA and SerialB. Hopefully that's not too painful at this point.

@WestfW
Copy link

WestfW commented Feb 26, 2020

Make SerialUSB0 an alias for the original SerialUSB, too?

@geertu
Copy link
Contributor Author

geertu commented Feb 26, 2020

I ported this to Teensy 4.0.

Nice!

I'm going to make one more change before releasing a beta test. Arduino's naming convention seems to be SerialUSB. We already support SerialUSB as an alias for Serial (and I believe Arduino does too on their board where they are the same). So I'm going to go with SerialUSB1 and SerialUSB2 rather than SerialA and SerialB. Hopefully that's not too painful at this point.

That makes perfect sense. I wasn't aware of SerialUSB, so that's why I went with A and B, to avoid interfering with the hardware serial numbering.

BTW, shouldn't usb_serial2* and usb_serial3* be renamed to usb_serial1* and usb_serial2*, too, to preserve consistency. Right now we have:
teensy3/usb_serial.h:extern usb_serial_class Serial;
teensy3/usb_serial2.h:extern usb_serial2_class SerialUSB1;
teensy3/usb_serial3.h:extern usb_serial3_class SerialUSB2;
teensy4/usb_serial.h:extern usb_serial_class Serial;
teensy4/usb_serial.h:extern usb_serial2_class SerialUSB1;
teensy4/usb_serial.h:extern usb_serial3_class SerialUSB2;

@PaulStoffregen
Copy link
Owner

I'm ok with the internal names not being consistent with the Arduino API names. At this point, I'm pretty happy with "ain't broke, don't fix".

@WestfW - Does Arduino use SerialUSB0, or Serial0, or "0" on the end of any of the port names for their boards? I do want the public API names to be consistent with the conventions Arduino is using.

@mjs513
Copy link
Contributor

mjs513 commented Mar 3, 2020

Kind of curious now that someone pointed this discussion out to me - but what changes are necessary to boards.txt to get it to work if I wanted to give it a test? Or is it too early to ask.

UPDATE: Forget I asked - figured it out dummy that I am. It works with T4 by the way.

@geertu
Copy link
Contributor Author

geertu commented Mar 3, 2020

Kind of curious now that someone pointed this discussion out to me - but what changes are necessary to boards.txt to get it to work if I wanted to give it a test? Or is it too early to ask.

UPDATE: Forget I asked - figured it out dummy that I am. It works with T4 by the way.

JFTR, for Teensy 3.1/3.2, add to hardware/teensy/avr/boards.txt:

teensy31.menu.usb.dualserial=Dual serial
teensy31.menu.usb.dualserial.build.usbtype=USB_DUAL_SERIAL
teensy31.menu.usb.tripleserial=Triple serial
teensy31.menu.usb.tripleserial.build.usbtype=USB_TRIPLE_SERIAL

@mjs513
Copy link
Contributor

mjs513 commented Mar 3, 2020

Yep - that's pretty much what I had done, except used Serial2 - Serial3 after usb.
Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants