第二章:触摸屏驱动架构概览

做驱动调优,首先得搞清楚你面对的是什么。触摸屏驱动看起来就是个“上报坐标”的模块,但里面的门道不少。我个人习惯把驱动架构拆成三层来看,这样排查问题会清晰很多。

2.1 三层驱动模型

智能座舱的触摸屏驱动,说白了就是下面这张图的结构。你想想看,从手指点到屏幕,到应用层响应,中间经过了三个关卡。

触摸屏驱动三层架构图 触摸屏驱动三层架构 硬件接口层(HAL) I²C / SPI / USB 总线通信 · 寄存器读写 · 中断处理 负责与触摸屏 IC 直接对话,获取原始触摸数据 核心处理层(Core) 数据滤波 · 坐标校准 · 多点追踪 · 手势识别 将原始数据转化为稳定的触摸事件 事件上报层(Input) Linux Input 子系统 · 多点触控协议(MT Protocol) 将触摸事件上报给上层应用框架

这三层各司其职,每一层都可能成为性能瓶颈。我遇到过不少案例,问题出在硬件接口层,大家却跑到上层去调参数,折腾半天没效果。

2.2 硬件接口层详解

这一层是驱动和芯片的“翻译官”。常见的通信接口有 I²C、SPI 和 USB。座舱里用得最多的是 I²C 和 SPI。

接口类型 典型速率 适用场景 调优关注点
I²C 400 kHz ~ 1 MHz 中低端座舱、电容屏 时钟频率、ACK 超时、中断延迟
SPI 10 MHz ~ 50 MHz 高端座舱、多点触控 时钟极性、相位、DMA 传输
USB 12 Mbps(全速) 外接触摸屏、调试 端点轮询间隔、传输缓冲区
我的经验: 调 I²C 时,先检查中断触发方式。我遇到过因为中断被其他高优先级设备抢占,导致触摸数据读取延迟超过 10 ms 的情况。改成边缘触发 + 线程化中断后,问题就解决了。

2.3 核心处理层

这一层是“大脑”。原始数据进来,经过滤波、校准、追踪,最后变成稳定的触摸事件。嗯,这里要注意,滤波算法选不好,反而会引入延迟。

常见的滤波方式有:

  • 均值滤波:简单粗暴,但会引入固定延迟(窗口大小 × 采样间隔)
  • 中值滤波:抗噪能力强,适合去除毛刺,但计算量大
  • 卡尔曼滤波:动态效果好,适合快速滑动场景,但参数调起来麻烦

我曾经在一个项目中,为了追求平滑度,把均值滤波窗口设到了 5。结果滑动时明显感觉“粘手”。后来改成自适应窗口——静止时用大窗口,滑动时用小窗口,效果好了很多。

2.4 事件上报层

这一层负责把处理好的数据“递”给上层。Linux 内核里用的是 Input 子系统,多点触控遵循 MT Protocol B 协议。

上报流程大致是:

  1. 调用 input_mt_slot() 设置当前槽位
  2. 调用 input_mt_report_slot_state() 报告触摸状态
  3. 调用 input_report_abs() 上报 X/Y 坐标
  4. 调用 input_sync() 同步事件

关键点: 上报频率不是越高越好。我见过有人把上报频率调到 200 Hz,结果 CPU 占用率飙升,反而导致系统卡顿。座舱场景下,100 Hz 左右通常就够用了。

2.5 驱动调优的切入点

了解了三层架构,调优就有了方向。我个人习惯按下面的优先级来排查:

优先级 排查层 常见问题 快速验证方法
高 硬件接口层 中断延迟、总线速率不足 用示波器抓 I²C/SPI 波形
中 核心处理层 滤波窗口过大、校准算法耗时 加时间戳日志,看每步耗时
低 事件上报层 上报频率不匹配、同步丢失 用 getevent 工具查看事件流
避坑指南: 我曾经一上来就调核心处理层的算法,折腾了两天没效果。后来发现是 I²C 总线被其他设备占用了,导致触摸数据读取间隔不稳定。记住,先排查硬件接口层,再动上层逻辑。

2.6 本章小结

触摸屏驱动架构并不复杂,但每一层都有它的脾气。硬件接口层决定了数据能不能“拿得到”,核心处理层决定了数据“好不好用”,事件上报层决定了数据“传得顺不顺”。

后面几章,我会带着大家深入每一层,讲讲具体的调优方法和实战案例。嗯,先从硬件接口层开始吧。