Skip to content

Custom baud rates - #19

Open
jorisvergeer wants to merge 1 commit into
jcurl:v2.xfrom
jorisvergeer:v2.x
Open

jorisvergeer wants to merge 1 commit into
jcurl:v2.xfrom
jorisvergeer:v2.x

Conversation

@jorisvergeer

Copy link
Copy Markdown

Hi,

I saw some todos regarding custom baud rates in your code.

I needed baud rate 345600 which is not a supported baud rate.

Here is a pull request with code for custom baud rates. I using information from:
http://www.home.unix-ag.org/simon/files/serial-linux.c
and
https://github.com/torvalds/linux/blob/master/drivers/usb/serial/ftdi_sio.c

It runs now for 5 minutes on my machine using a FTDI chip.

commit ca3966446039aa557ff5eda364fbc97de7a35898
Author: vagrant <vagrant@vagrant.vm>
Date:   Tue Apr 11 16:10:17 2017 +0000

    Fix build issues and a missed check

commit 9ee3d50cc581053b05e380b6eb6454ee19150e26
Author: Joris Vergeer <j.vergeer@agis.nl>
Date:   Tue Apr 11 18:01:20 2017 +0200

    Custom baud
@jcurl

jcurl commented Apr 11, 2017

Copy link
Copy Markdown
Owner

Cool! Be patient while I get around to testing it with the serial devices I have. I'm hoping over the Easter break.

@jorisvergeer jorisvergeer changed the title Squashed commit of the following: Custom baud rates Apr 11, 2017
@jorisvergeer

Copy link
Copy Markdown
Author

I might need to add some cleanup code around the close event

@jorisvergeer

Copy link
Copy Markdown
Author

Also I was a bit lazy with returned errors

@jcurl

jcurl commented Apr 11, 2017

Copy link
Copy Markdown
Owner

I was also thinking, because the custom baudrate is OS specific, it might make sense to put it in its own file, and have the CMakeLists.txt compile the file depending on the OS it detects.

@jcurl

jcurl commented Apr 11, 2017

Copy link
Copy Markdown
Owner

What chipsets have you already tested with, and what OS are you using?

@jorisvergeer

Copy link
Copy Markdown
Author

There might only be a handful of drivers that support the custom_divisor stuff although I am not sure.

@jorisvergeer

jorisvergeer commented Apr 11, 2017

Copy link
Copy Markdown
Author

I only tested with FTDI.
Windows uses its own implementation. I only touched the linux part.
It works on Windows and Linux in my machine ;)

@jcurl

jcurl commented Apr 11, 2017

Copy link
Copy Markdown
Owner

I have PL2303, an original 16550A in my laptop docking station and another USB (SCM2xxx) that I'll test with.

@Rafael-SOWNet

Copy link
Copy Markdown

Data point from using this in production, in case it's useful for deciding how to land custom baud rates.

We hit the same wall (FTDI FT4232H on linux-arm64, needing 250000 / 1562500 / 3125000 / 6250000 — none of which have a POSIX B… constant). Rather than patch libnserial, we set the rate from the managed side with termios2 + BOTHER, which turned out to have two practical advantages over the TIOCSSERIAL + custom_divisor + B38400 approach in this PR:

1. It's exact rather than rounded. custom_divisor gives you baud_base / divisor, so the achieved rate is whatever that division lands on. termios2 takes the rate directly in c_ispeed/c_ospeed. Verified on a real FT4232H — every rate reported back by the kernel exactly, no substitution:

38400 115200 250000 500000 1000000 1562500 3125000 6250000

2. It needs no native rebuild. Termios settings on Linux belong to the TTY, not to a file descriptor, so opening a second fd to the same device and issuing TCSETS2 also changes the speed of the port SerialPortStream already has open. That means it works against the stock NuGet package.

Sketch (ioctl values are the same on x86_64 and aarch64, both asm-generic):

#define TCGETS2 0x802C542A
#define TCSETS2 0x402C542B
#define CBAUD   0x0000100F
#define BOTHER  0x00001000

struct termios2 t;
ioctl(fd, TCGETS2, &t);
t.c_cflag = (t.c_cflag & ~CBAUD) | BOTHER;
t.c_ispeed = t.c_ospeed = baud;
ioctl(fd, TCSETS2, &t);

One thing worth doing either way: read the settings back after setting them and compare against what was requested. The kernel (or the driver) can quietly program something else, and without the check that looks indistinguishable from a working switch — we chased a bug for a while that turned out to be exactly this class of silent mismatch.

Also, separate from custom rates but adjacent to the // TODO: Update the serial port baud rate if already opened this PR touches: that TODO bites for standard rates too. Setting SerialPortStream.BaudRate on an already-open port updates handle->baudrate/cbaud but never reaches tcsetattr, since serial_setproperties() is only called from Open(). It throws nothing, so the port keeps transmitting at the old rate while the application believes it switched. The XML doc does warn about it, but it's an easy one to lose a day to. Happy to open a separate issue if that'd be useful.

Thanks for the library — it's been solid for us otherwise.

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.

3 participants