Re: Precise timing in ldisc? tty_put_char() in hrtimer context?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Jan 07, 2025 at 07:07:42PM +0100, Tomáš Mudruňka wrote:
> i am implementing niche rs485-based serial protocol as a tty line
> discipline linux module. Requirement is to hit transmission window
> with precision in low hundreds of microseconds (eg. +-200 uS).
> Transmit window starts 500 uS after message is received.
> 
> It seems that hardware driver calls tty_receive_buf2() with sufficient
> latency, so my idea was to start hrtimer using hrtimer_start() inside
> of tty_receive_buf2(). And then in hrtimer handler call
> for(...){tty_put_char(tty,...)} or tty->ops->write(), but it seems not
> to be a good practice according to my online research. They say it's
> recommended to call tty_put_char() from workqueue, but documentation
> also says that calling a workqueue might introduce latency of couple
> milliseconds, since it's scheduled thread context.

It's going to depend on the hardware driver, but note that the 8250
driver calls tty_receive_buf2() from a workqueue.  So you have one
scheduler thread context hop already.

One of the issues here is that serial port hardware is... interesting,
and the original design goal of the serial and tty layers included
supporting hardware with no FIFO's, so when receiving at 11,520
characters per second, there would be an interrupt every 8 uS.  The
goal was to make sure that we didn't lose any characters when running
at that rate, as well as being able to support multiple 115k baud
serial ports running at full speed on relatively 40 MHz 386
processors.  So the whole system is designed to optimize for
throughput at low oeverhead, and not latency.

If you only care about making it work on your specific serial port
hardware, you might be able to make things work, but some serial ports
have been known to drop transmit interrupts, so there are timeout
mechanisms which will wait for a little bit more time than needed to
empty the FIFO, and if we don't get an transmit interrupt and there
are characters waiting to be transmitted, we'll check to see if the
UART is ready to receive more characters and send the characters as a
backup mechanism if the transmit interrupt gets lost --- which some
hardware would be prone to do.  There is a lot of dodgy serial port
hardware out there.

So it's not just that Linux isn't a realtime OS.  It's that tty layer
wasn't architected for your use case.  Ultimately, if you want the
best latency, you might need to replace the driver which one that
polls and burns a full CPU instead of depending on interrupts, and
then bypass the tty layer altogether.  That would make your solution
specific to a particular hardware back-end, but full generality isn't
possible in any case, not if you are trying to hit tight latency
guarantees.

For example, there is one serial port hardware which would support up
to 128 serial ports, and doesn't use interrupts at all, but instead
has deep hardware buffers, and the driver runs interly off of timer
callbacks.  That's one case where the *hardware* has been optimized
for throughput and low CPU overhead for a very large number of active
serial ports (think: modem banks), and for which latency is terrible,
but that was explicitly designed by the hardware manufacturer for that
use case and a very different set of design constraints than what you
are trying to achieve.  So if you tried to run your rs485 protocol on
that hardware, it would very likely be hopeless.

Cheers,

					- Ted




[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux PPP]     [Linux FS]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Linmodem]     [Device Mapper]     [Linux Kernel for ARM]

  Powered by Linux