Linux硬件中断时间戳实现:I2C、UART等信号接收打戳方案咨询
两种方案均可行,适用场景和实现思路如下
方案1:修改内核驱动生成时间戳(精度最高)
- 实现逻辑:在驱动的接收中断回调函数中,直接调用内核时间接口获取时间戳。常用接口包括
ktime_get_real_ns()(获取墙钟时间,纳秒级)、ktime_get_boottime_ns()(包含系统休眠时间的单调时间),拿到时间戳后可以选择两种方式带出内核:- 方式1:修改驱动对应字符设备的读接口返回结构体,在有效载荷前后追加时间戳字段,用户态读取数据时可以直接获取
- 方式2:通过
netlink或者ioctl回调将时间戳和数据绑定返回
- 优势:时间戳在硬件中断触发后立刻获取,几乎没有额外延迟,精度可达微秒甚至纳秒级,适合对时间精度要求极高的场景
- 注意点:需要适配对应硬件的驱动源码,不同厂商的I2C/UART控制器驱动实现存在差异,另外修改后的驱动需要重新编译签名后,才能加载到启用了Secure Boot的系统上
方案2:用户态追加时间戳(实现简单,兼容性好)
- 实现逻辑:不需要修改内核代码,驱动正常将数据上报到用户态,你可以选择两种架构实现打戳:
- 方式1:直接在读取串口/I2C设备的用户程序中,调用
clock_gettime()接口获取系统时间后和数据绑定,不需要走共享内存 - 方式2:如果有多进程处理需求,可以用共享内存+环形队列的方式,数据采集进程从字符设备读取数据后写入共享内存队列,专门的打戳进程/后处理进程读取队列时追加时间戳再做后续处理
- 方式1:直接在读取串口/I2C设备的用户程序中,调用
- 优势:开发成本极低,不需要内核开发能力,兼容所有标准Linux发行版的默认驱动
- 精度说明:如果用
read()阻塞读设备,收到数据后立刻打戳,延迟通常在毫秒级以内,绝大多数工业采集、普通数据传输场景都能满足要求;如果要进一步降低延迟,可以把用户进程优先级调到实时优先级(用chrt命令设置)、绑核运行,减少调度延迟
选型建议:如果你的场景对时间误差容忍度在1ms以上,优先选用户态方案,开发和维护成本更低;如果要求微秒级的时间精度,再考虑修改驱动的方案。
内容的提问来源于stack exchange,提问作者FourierFlux
相关产品推荐
相关产品推荐

