Page MenuHomeFreeBSD

Add TIOCFBAUD UART ioctl to allow fractional baudrates
Needs ReviewPublic

Authored by shurd on Jul 23 2018, 4:58 AM.

Details

Summary

Amateur radio uses 22ms bit timings for RTTY. This translates
to a baudrate of 45.45 repeating, so FreeBSD is not a good choice for
hardware-keyed FSK. Further, the Oxford PCIe driver defaults to a
clock rate that is too high to support 45 baud at all.

This allows notifying puc(4) of an upcoming baudrate so it can adjust
the prescaling to allow it. The Oxford drivers will now set up the
prescaler and oversampling to allow the closest possible solution for
a baud rate. This is currently only used by the new ioctl. Also, the
clock rate for the Oxford PCIe parts is 62.5MHz, it is not a multiple
of 1.8432MHz, so this also makes timing better for these devices.

Test Plan

So much testing... first, ensure that 45.45 baud works and
is correct. Then ensure the Oxford parts continue working for other
baudrates. Finally, use the serial port as a console to make sure
I haven't broken anything else.

Diff Detail

Repository
rS FreeBSD src repository
Lint
Lint OK
Unit
No Unit Test Coverage
Build Status
Buildable 19139
Build 18764: arc lint + arc unit

Event Timeline

shurd created this revision.Jul 23 2018, 4:58 AM
imp added inline comments.Jul 23 2018, 7:48 AM
sys/dev/uart/uart_tty.c
264

that's not going to fly. why is puc special? and why does that specialness have to be handled here?

shurd added inline comments.Jul 23 2018, 5:14 PM
sys/dev/uart/uart_tty.c
264

Yeah, the gross layer violation here is the biggest problem. As for why it's special, it's the source of the rclk value and where the chip-specific code for the OXPCIe958 lives.

I think the best thing will be to add an interface to uart_if.m and have this handled in uart_bus_puc.c. I'll work on that tonight.

shurd updated this revision to Diff 45752.Jul 24 2018, 2:17 AM

Fix up puc(4) abuse... add new method to serdev, update the termios info.
Adjust rclk again when using tcsetattr() so we don't get stuck with a
weird rclk.
Add a TIOCGFBAUD to get the current exact baudrate.
Use a struct instead of an array of integers.
Various bug fixes.

Some of the puc changes are still a bit suspect, particularly moving
puc_port into a header file, but it seems to be the least painful way
of doing it.

shurd marked 2 inline comments as done.Jul 24 2018, 2:28 AM
shurd updated this revision to Diff 45753.

Clean up some bad bits in the past update.

shurd updated this revision to Diff 45818.Jul 25 2018, 8:34 AM

Since MCR bit 7 is used for the prescaler, we need to update the
cached copy of the MCR after a call to SERDEV_ADJUST_RCLK.

shurd updated this revision to Diff 45821.Jul 25 2018, 9:29 AM

After changing the baud rate, we need to update the watermarks it seems.

shurd updated this revision to Diff 45854.Jul 26 2018, 12:40 AM

Allow preventing RTS/DTR from being asserted on open()

RTTY Radios are generally wired up to start transmitting when RTS is
asserted. While most older radios use relays, so it can be turned off fast
enough to prevent a transmission, newer radios use solid-state switching.
This change allows preventing RTS from being pulsed. Since many of the
searches online for an existing API resulted in threads where people wanted
to avoid asserting DTR on open(), added that as well.

This isn't an ideal interface, since it requires you to use stty on the init
device before opening it, but it's certainly easier than adding yet another
set of devices to the /dev/tty and /dev/cua family.

This changes means perhaps adding an example to /etc/rc.d/serial and even
more documentation to touch once this gets into a stable state (termios,
stty).

shurd updated this revision to Diff 47244.Aug 24 2018, 4:21 PM

Fix builds on GCC targets

Warning promoted to error when testing if a uint16_t is > 65535.

Allow preventing RTS/DTR from being asserted on open()
RTTY Radios are generally wired up to start transmitting when RTS is
asserted. While most older radios use relays, so it can be turned off fast
enough to prevent a transmission, newer radios use solid-state switching.
This change allows preventing RTS from being pulsed. Since many of the
searches online for an existing API resulted in threads where people wanted
to avoid asserting DTR on open(), added that as well.
This isn't an ideal interface, since it requires you to use stty on the init
device before opening it, but it's certainly easier than adding yet another
set of devices to the /dev/tty and /dev/cua family.

I would argue that this is an ideal interface, and adding another set of devices would be somewhat hackish feeling. All of the times that I've wanted this, I really wanted to -rtsdtr on the .init node instead of teaching software yet another pattern of TTY names to deal with on FreeBSD. Additionally, each of these times I didn't really want to access the device two different ways- either it coped well with DTR being asserted on open, or it took DTR to mean something that I would much prefer to deliberately control (e.g. board reset).

I'd really like to see this part split out into a separate review and committed soon, because it shouldn't see any contention- it adds control that is desirable to the people that know they need it, and doesn't really affect anyone else.

shurd added a comment.Apr 19 2019, 5:50 PM

I'd really like to see this part split out into a separate review and committed soon, because it shouldn't see any contention- it adds control that is desirable to the people that know they need it, and doesn't really affect anyone else.

I had mostly forgotten about this. I'll split it out this weekend and maybe clean the rest of it up. Thanks for reminding me.