c - 从并行端口读取 4 µs 长 +5V TTL——何时使用内核中断

标签 c linux linux-kernel hardware-interface

我有一个运行技巧的实验盒,每 100 毫秒左右,就会在 TTL 线上发出一个 4 微秒长的 +5V 电脉冲。发生这种情况的确切时间无法提前知晓,但它很重要——所以我想使用基本上运行该实验的 Red Hat 5.3 计算机来为该 TTL 提供服务,并创建一个荣耀的时间戳。

目前,我所做的是将 TTL 连接到 linux 机器上并行端口的引脚 13(STATUS_SELECT,并行端口上的输入线之一),生成一个在实验开始时处理,使用 chrt 将其预定优先级更改为 99 - 即高 - 然后在 while< 中重复轮询并行端口 循环直到引脚变高。然后我创建一个准确的时间戳,并以非阻塞方式将其写入磁盘。

显然,这是低效的——有时进程会被挂起,并且会错过 TTL。由于计算机本身正忙于做其他事情(即从我的实验套件——核磁共振扫描仪获取数据!),这种情况经常发生。轮询很容易,但可能很糟糕。

我的问题是:当 TTL 发生时快速做某事似乎是计算的基础,但据我所知,只有内核才能处理 Linux 上的中断模块。并口可以产生中断,库如paraport让您相对快速构建内核模块,您必须在其中提供自己的处理程序。

是处理此问题并在 TTL 进入时为实验创建准确(±25 毫秒)时间戳的最佳方法——编写一个内核模块,为/proc 中的某处提供最近的中断列表,并且然后再用正常的过程读出来?这种方法是行不通的,而且 CPU 效率非常低——还是打开一堆蠕虫来处理我不知道的中断优先级?

最重要的是,这似乎应该是一个已解决的问题 - 是吗?如果是这样,是否有智者愿意为我指出正确的方向?坦率地说,编写一个内核模块似乎是一项艰巨而冒险的工作,但感觉它应该很简单。

最佳答案

“如果您是内核模块,则只能在 Linux 上处理中断”这一前提否定了一些相当常见且有效的策略。

响应用户空间中断(尤其是不常见的中断)的简单操作过程是让一个驱动程序创建一个内核设备(或者在某些情况下是 sysfs 节点),其中有一个 read() 或者一个自定义的 ioctl() from userspace 将阻塞直到中断发生。您必须检查默认的并行端口驱动程序是否支持此功能,但它在嵌入式板上的 GPIO 驱动程序中非常常见,并且可以将基本方案借用到并行端口中 - 前提是硬件支持 true打扰

如果目标是非常精确的计时,您可能会更好地自定义内核模块以在其中记录时间戳,并实现一种机制,在中断发生之前,来自用户空间的 read() 会阻塞,然后获取内核已经记录的时间戳作为读取数据 - 从而避免唤醒用户空间和回调内核以获取时间的可变延迟。

在可用并行端口是不支持它们的部分或间接实现的情况下,您还可以将真正的本地总线串行端口(如果存在)视为具有备用中断功能的接口(interface)。

在您唯一可用的接口(interface)是间接和高延迟的接口(interface)(例如 USB)的情况下,或者您希望大量独立于主机和操作系统的情况下,使用外部微 Controller 可能确实有意义。在那种情况下,您可能会尝试从主机系统设置微处理器的时钟,然后让它在每次看到事件时给您时间戳消息。如果您的实验只需要时间戳在给定的实验 session 中彼此相关,那么这应该可以正常工作。但是,如果您需要在 USB 延迟之间建立绝对时间同步,则可能需要进行一些仔细的往返测量,然后估计延迟以对其进行补偿(有关极端示例,请参见 NTP)。

关于c - 从并行端口读取 4 µs 长 +5V TTL——何时使用内核中断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24707931/

相关文章:

c - open(O_CREATE) 权限的八进制字符串到整数

linux - 如何从文本文件获取输入并将其用作 shell 脚本中的变量?

linux - 如何低级调试卡住的 Ubuntu 内核?

android - Android是否支持虚拟内存

C 和 for 循环

c - 取消引用指针

c - 加载共享对象的故障安全方式

linux - 如何检查 Ubuntu 上是否安装了 openSSH

linux - 如何在不将 Linux 102221.pdf 中的扩展名更改为 102221_name.pdf 的情况下重命名文件

linux - 如何从 linux 内核核心转储中找到 'HZ' 值?