我有一个运行技巧的实验盒,每 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/