想要确保 tty 写入按给定时间戳推送到硬件(UART)或失败

发布于 2024-10-31 03:08:22 字数 472 浏览 6 评论 0原文

我需要将一些数据写入串行端口,同时确保如果无法通过给定的“到期时间戳”写入数据,它将返回失败代码。数据来自不同的串行端口,到期时间来自第三个设备。

我最初的计划是在内核空间中实现所有这些,但我得出的结论是,由于它需要访问 3 个设备,因此最好在用户空间中桥接它们;不幸的是,这使得时机变得困难。

尽管花费了大量时间阅读 LDD3 并查看 tty 子系统和相关代码,但我在解决如何实现这一目标时遇到了困难。我实际上想向现有的串行端口/tty 设备添加功能,以便我可以使用 ioctl 或编写指示数据和到期时间的转义序列。

我在这里可以控制内核源代码,因为它已经被分发了,如果我可以仅使用内核模块来实现这一点,那就太好了。如果重新刷新内核是必要的,那就这样吧。

任何人都可以提供有关将此过期写入添加到现有串行/tty组合的指导,或者关于什么可能是更好的方法来解决此问题的其他建议吗?

提前致谢 - 如果信息不够,我们深表歉意,如果需要,我会添加详细信息。

I need to write some data to a serial port whilst ensuring that if it can't be written by a given 'expiry timestamp' that it will return failure code. The data comes from a different serial port, and the expiry time from a 3rd device.

My original plan was to implement all of this in kernelspace, but I concluded that since it needs access to 3 devices it'd probably be better to bridge them in userspace; that unfortunately makes the timing difficult.

Despite spending some significant time reading LDD3 and looking through tty subsystem and related code, I'm having trouble working out how to achieve this. I effectively want to add functionality to an existing serial port/tty device so that I can use ioctl or write an escape sequence indicating the data and expiry time.

I have control over the kernel source here, though since it's already been distributed if I can achieve this solely with a kernel module that would be superb. If reflashing the kernel is essential then so be it.

Can anyone provide either guidance on adding this expiring-write to existing serial/tty combination, or other advice on what might be a better way to go about this?

Thanks in advance - apologies if not enough info, I'll add details if they're required.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

风月客 2024-11-07 03:08:22

我建议完全在用户空间中执行此操作。这背后有两个假设:没有流量控制,并且所需的精度约为 50 毫秒或更差。

缺乏流量控制至关重要:硬件流量控制可能会导致恶意远程设备通过延迟 UART FIFO 中的字节来欺骗您。软件流控制可以阻止设备驱动程序中的数据。完成此操作后,数据将以所需的波特率毫无延迟地流过 UART。如果您确保在每次写入设备之前内核缓冲区为空,您将实现您的计时。

我的解决方案的组成部分是:

  1. 使用 SCHED_FIFO 运行应用程序以避免抢占。
  2. 选择要发送的消息。您没有说明您的消息是否有排序限制。如果没有,您可能需要实现一个调度程序来决定消息顺序。最早的截止日期首先可能会起作用。
  3. 始终在写入之前tcdrain
  4. 一旦您知道输出缓冲区为空,请检查是否有足够的时间让所有字节以选定的波特率传输。如果剩余时间不足,则发出故障代码并返回顶部。
  5. 写入消息字节。

要处理其他端口,您需要使用多个线程或带有超时的 select 。如果您使用select,请记住您的线程将在tcdrain 中被阻塞。

如果您需要更精确的计时,请考虑使用专用微控制器。

I propose doing this entirely in userspace. There are two assumptions behind this: you don't have flow control, and the precision required is around 50ms or worse.

The lack of flow control is essential: hardware flow control can allow a hostile remote device to cheat you, by stalling bytes within the UART FIFO. Software flow control can stall data in the device driver. With that out of the way, data will flow through the UART at the required baud rate without delay. If you ensure that the kernel buffers are empty before each write to the device, you will achieve your timing.

The parts of my solution are:

  1. Run your application using SCHED_FIFO to avoid pre-emption.
  2. Select a message to send. You don't say if there is an ordering constraint on your messages. If there isn't, you may want to implement a scheduler to decide the message order. Earliest deadline first would probably work.
  3. Always tcdrain before writing.
  4. Once you know the output buffer is empty, check that there is enough time for all the bytes to travel at the selected baud rate. If there is insufficient time remaining, emit the failure code and return to the top.
  5. Write the message bytes.

To handle the other ports you'll need to use multiple threads or select with timeouts. If you use select, remember that your thread will be blocked in tcdrain.

And if you need much more precise timing consider using a dedicated microcontroller.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文