ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

RK3568嵌入式Linux下GT911触摸屏驱动调试与tslib校准实战

RK3568嵌入式Linux下GT911触摸屏驱动调试与tslib校准实战 1. 项目缘起与整体设计思路GT911 这颗触摸屏控制芯片做嵌入式 Linux 的人大概率都碰过。它便宜、供货稳、驱动成熟从国产平板到工业 HMI 到处都能见到它的身影。但“驱动成熟”和“一次点亮”之间往往隔着好几天的调试。我最近在一个基于瑞芯微 RK3568 的板子上重新走了一遍 GT911 的完整调试链路从设备树配置一直做到 tslib 校准中间踩的坑不算少索性把整个过程整理出来给后来人省点时间。这个项目的核心目标很明确让一块 1024x600 的 MIPI 屏配上 GT911 电容触摸在 Linux 系统下实现准确、稳定的触摸响应并且通过 tslib 完成五点校准保证触摸坐标和显示坐标严格对齐。适合谁看如果你正在做 RK3568、RK3399 或者全志、晶晨这类平台的触摸屏适配或者你手头有一块 GT911 但 I2C 通信死活不通、中断不触发、坐标偏移这篇内容应该能帮上忙。即使你是刚接触设备树的新手我也会把每一步的“为什么”讲清楚而不是只丢一堆配置让你抄。整体方案上我选择的是“内核驱动 tslib 用户态校准”的经典组合。有人会问现在很多方案直接用 libinput 或者 Wayland 下的触摸处理为什么还要用 tslib原因在于工业场景和传统 Qt 应用里tslib 的校准机制更直接、更可控尤其是电阻屏和早期电容屏混用的环境下tslib 的ts_calibrate能快速解决坐标映射问题。GT911 本身是电容屏理论上不需要校准但实际项目中由于屏幕旋转、分辨率缩放、边缘触控偏差等原因校准仍然是保证体验的关键一步。设备树配置这块RK3568 的 I2C 控制器和 GPIO 中断配置是重点。GT911 挂载在 I2C 总线上通过中断引脚通知主机有触摸事件通过复位引脚完成上电初始化。这三个信号——I2C 的 SDA/SCL、中断 INT、复位 RST——任何一个配错驱动都起不来。我见过太多人卡在“i2c transfer failed”或者“gt911 2-005d: gt911_probe: request irq failed”这类报错上其实根源都在设备树。提示GT911 的 I2C 地址由 INT 引脚在上电复位时的电平决定常见地址是 0x5D 和 0x14。如果设备树里写的地址和实际不符probe 会直接失败连报错都未必明显。设计思路上我坚持“先通 I2C再通中断最后调坐标”的顺序。很多人一上来就改分辨率、改旋转结果底层通信都没通改什么都没用。所以下面的内容会严格按照这个顺序展开每一步都有验证方法确保你在进入下一步之前当前环节是确定没问题的。2. 设备树配置的核心细节与实操要点2.1 I2C 节点与 GT911 子节点的正确写法RK3568 的设备树里I2C 控制器通常有多个比如 i2c0 到 i2c5。GT911 一般挂在某个可用的 I2C 上我这次用的是 i2c3。先看 I2C 控制器的配置关键是时钟频率和引脚复用。GT911 支持标准模式 100kHz 和快速模式 400kHz我一般用 400kHz响应更快但前提是走线不能太长否则波形质量下降会导致通信失败。i2c3 { status okay; clock-frequency 400000; pinctrl-names default; pinctrl-0 i2c3m0_xfer; gt911: gt9115d { compatible goodix,gt911; reg 0x5d; interrupt-parent gpio3; interrupts RK_PA5 IRQ_TYPE_EDGE_FALLING; reset-gpios gpio3 RK_PA4 GPIO_ACTIVE_LOW; irq-gpios gpio3 RK_PA5 GPIO_ACTIVE_HIGH; pinctrl-names default; pinctrl-0 gt911_int; touchscreen-size-x 1024; touchscreen-size-y 600; touchscreen-inverted-x; touchscreen-inverted-y; status okay; }; };这段配置里compatible必须是goodix,gt911这是内核驱动匹配的关键。reg是 I2C 从地址0x5d 对应 INT 引脚在上电时为高电平的情况。interrupts里我用了下降沿触发因为 GT911 的中断是低电平有效触摸时拉低松开后拉高。reset-gpios和irq-gpios分别对应复位和中断引脚注意GPIO_ACTIVE_LOW和GPIO_ACTIVE_HIGH的区别复位引脚通常是低电平复位所以用GPIO_ACTIVE_LOW。touchscreen-size-x和touchscreen-size-y填的是屏幕分辨率这个值会影响驱动上报的坐标范围。touchscreen-inverted-x和touchscreen-inverted-y是坐标反转如果触摸方向和显示方向相反就加上这两个属性。我这次因为屏幕是竖屏装横用所以两个都加了。注意pinctrl-0里引用的gt911_int需要在 pinctrl 节点里定义把 INT 引脚复用为 GPIO 功能并配置上拉或下拉。如果 INT 引脚没有正确复用中断永远不会触发。2.2 中断引脚与复位引脚的时序陷阱GT911 的上电时序是有讲究的。复位引脚拉低至少 10ms然后拉高之后 INT 引脚的电平决定了 I2C 地址。如果复位和 INT 的时序不对芯片可能进入错误的工作模式甚至不响应 I2C。我在第一次调试时就遇到了这个问题复位引脚配置成了GPIO_ACTIVE_HIGH结果芯片一直处于复位状态I2C 扫描不到设备。正确的做法是在设备树里把复位引脚配成低电平有效驱动在 probe 时会先拉低复位延时再拉高。同时INT 引脚在上电时要保持高电平这样芯片才会选择 0x5d 地址。如果 INT 在上电时是低电平地址会变成 0x14。我建议在硬件设计阶段就用上拉电阻把 INT 拉到高电平软件上再配置成中断模式。另外中断触发方式我试过IRQ_TYPE_EDGE_FALLING和IRQ_TYPE_LEVEL_LOW实测下来下降沿更稳定因为 GT911 的中断信号是一个脉冲不是持续低电平。如果用 level 触发可能会在中断处理函数里反复进入导致 CPU 占用率飙升。2.3 引脚复用与 GPIO 配置的常见错误RK3568 的引脚复用功能很灵活但也容易配错。比如 I2C3 的 SDA 和 SCL 可能和别的功能复用如果 pinctrl 没配对I2C 通信直接失败。我一般会在设备树里明确指定pinctrl-0 i2c3m0_xfer其中i2c3m0_xfer是 RK3568 的 I2C3 引脚组定义通常在rk3568-pinctrl.dtsi里已经写好了。对于 INT 和 RST 引脚需要自己定义 pinctrl 节点pinctrl { gt911 { gt911_int: gt911-int { rockchip,pins 3 RK_PA5 RK_FUNC_GPIO pcfg_pull_up; }; gt911_rst: gt911-rst { rockchip,pins 3 RK_PA4 RK_FUNC_GPIO pcfg_pull_up; }; }; };这里RK_FUNC_GPIO表示把引脚复用为普通 GPIOpcfg_pull_up是上拉配置。INT 引脚上拉可以保证空闲时为高电平触摸时被 GT911 拉低产生下降沿。RST 引脚上拉则保证复位后为高电平芯片正常工作。提示如果你在dmesg里看到gt911 3-005d: Unexpected firmware version或者I2C communication failed先检查 pinctrl 配置再检查硬件上拉电阻是否焊接。3. 驱动加载与 I2C 通信验证3.1 内核配置与驱动编译GT911 的驱动在内核里是CONFIG_TOUCHSCREEN_GOODIX路径在drivers/input/touchscreen/goodix.c。RK3568 的 SDK 里一般默认开启但如果你用的是自己裁剪的内核需要确认这个配置是y或者m。我习惯编成模块方便调试时动态加载。编译完成后把goodix.ko推到板子上insmod goodix.ko然后看dmesg。正常的日志应该是这样的[ 12.345678] gt911 3-005d: gt911_probe: start [ 12.456789] gt911 3-005d: GTP version: 0x1060 [ 12.567890] gt911 3-005d: GTP config version: 0x5a [ 12.678901] input: gt911 as /devices/platform/fe5c0000.i2c/i2c-3/3-005d/input/input2如果看到GTP version和input设备注册成功说明 I2C 通信和中断都正常了。如果卡在gt911_probe: start之后没有下文大概率是 I2C 读写出错需要检查硬件连接和设备树地址。3.2 用 i2c-tools 快速定位通信问题在驱动加载之前我强烈建议先用i2c-tools扫一遍总线。i2cdetect -y 3会列出 I2C3 上所有响应的地址。如果 GT911 正常你应该能看到5d或者14被标记出来。如果什么都没扫到说明硬件连接或者引脚复用有问题这时候去调驱动是白费力气。我遇到过一种情况i2cdetect能扫到 0x5d但驱动加载后读版本号失败。后来发现是 I2C 时钟频率太高400kHz 下波形畸变降到 100kHz 就正常了。所以如果你扫到了地址但驱动报错不妨把clock-frequency改成100000试试。注意有些板子的 I2C 上拉了 4.7k 电阻有些是 10k如果上拉太弱高速通信时上升沿变缓也会导致通信失败。硬件上可以用示波器看 SDA/SCL 波形软件上先降速验证。3.3 中断触发验证与 input 设备确认I2C 通了之后下一步是确认中断。cat /proc/interrupts | grep gt911可以看到中断号是否注册以及中断计数是否在触摸时增加。如果计数一直是 0说明中断没触发。这时候要检查 INT 引脚的 pinctrl 配置、上拉电阻、以及 GT911 的固件配置里中断模式是否正确。触摸时evtest是最直接的验证工具。evtest /dev/input/event2event 号根据实际情况会打印出触摸事件的坐标、压力值。如果能看到ABS_MT_POSITION_X和ABS_MT_POSITION_Y的变化说明驱动已经正常上报数据了。如果坐标范围不对比如 X 最大只有 800 而不是 1024那就要回头检查touchscreen-size-x的设置。4. tslib 校准全流程与坐标映射4.1 tslib 编译与配置文件生成tslib 的编译不复杂但依赖 libevdev 和 libinput 的某些头文件。我一般用 buildroot 或者 Yocto 直接集成如果手动编译./configure --prefix/usr --enable-staticno然后make make install就行。安装完成后/etc/ts.conf是核心配置文件里面定义了触摸屏的输入模块和过滤模块。默认的ts.conf内容大概是module_raw input module pthres pmin1 module variance delta30 module dejitter delta100 module linearmodule_raw input表示从 Linux input 子系统读取原始数据。pthres是压力阈值variance和dejitter是去抖和滤波linear是线性校准模块。对于 GT911 这种电容屏pthres可以设小一点因为电容屏没有物理压力压力值通常是固定或者模拟的。4.2 五点校准的操作步骤与参数解读校准前先设置环境变量export TSLIB_TSDEVICE/dev/input/event2 export TSLIB_CALIBFILE/etc/pointercal export TSLIB_CONFFILE/etc/ts.conf export TSLIB_PLUGINDIR/usr/lib/ts export TSLIB_CONSOLEDEVICEnone export TSLIB_FBDEVICE/dev/fb0然后运行ts_calibrate屏幕上会出现五个十字光标依次点击。点击完成后/etc/pointercal会生成七个参数格式是a0 a1 a2 b0 b1 b2 c这些参数构成了一个线性变换矩阵把触摸坐标映射到屏幕坐标。具体来说屏幕坐标 X (a0 * raw_x a1 * raw_y a2) / cY (b0 * raw_x b1 * raw_y b2) / c。如果校准后触摸仍然偏移可以手动微调这些参数但一般不建议因为ts_calibrate的精度已经够用了。提示如果ts_calibrate点击时十字光标不动或者点击后没有反应先确认TSLIB_TSDEVICE指向的 event 设备是否正确再用ts_test验证原始数据是否正常。4.3 校准后坐标偏移的排查思路校准后坐标偏移常见原因有三个一是touchscreen-inverted-x/y和 tslib 的校准矩阵冲突二是屏幕旋转后没有重新校准三是pointercal文件被覆盖或者权限不对。我遇到过一次校准后 X 轴反向后来发现是设备树里加了touchscreen-inverted-x但 tslib 校准时又做了一次反转两次反转抵消了。解决办法是去掉设备树里的反转属性只用 tslib 校准。另外如果应用层用的是 Qt还需要设置QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS或者QT_QPA_GENERIC_PLUGINStslib让 Qt 走 tslib 的校准数据。否则 Qt 直接读 input 设备校准就白做了。5. 常见问题速查与避坑经验5.1 I2C 通信失败问题排查表现象可能原因排查方法i2cdetect 扫不到地址硬件连接不良、引脚复用错误检查 SDA/SCL 焊接、pinctrl 配置扫到地址但读版本失败I2C 时钟太快、上拉电阻太弱降速到 100kHz、检查上拉电阻驱动 probe 失败设备树地址错误、复位时序不对确认 reg 地址、检查 reset-gpios中断计数不增加INT 引脚配置错误、上拉缺失检查 pinctrl、测量 INT 电平5.2 触摸坐标异常与校准失效坐标异常的表现很多触摸位置和显示位置差一个固定偏移、X 和 Y 互换、边缘触摸不灵敏。固定偏移通常是校准问题重新跑ts_calibrate就能解决。X/Y 互换一般是设备树里的touchscreen-swapped-x-y属性没加或者屏幕旋转后没有调整。边缘不灵敏可能是touchscreen-size-x/y设大了实际触摸区域比屏幕小需要根据实际触摸范围调整。我个人的经验是GT911 的固件里有一组配置参数包括触摸阈值、滤波系数等可以通过 I2C 读写。如果边缘触摸始终不好可以尝试更新 GT911 的固件配置但这一步风险较高建议在厂家支持下进行。5.3 屏幕旋转后的触摸适配RK3568 的显示旋转可以在设备树里改也可以在应用层用weston或者xrandr旋转。但触摸的旋转必须和显示同步否则触摸方向就乱了。如果显示旋转了 90 度触摸也需要在设备树里调整touchscreen-inverted-x/y和touchscreen-swapped-x-y的组合。我一般会做一个表格把四种旋转角度对应的属性组合列出来调试时直接查表。显示旋转触摸属性组合0 度无90 度swapped-x-y inverted-x180 度inverted-x inverted-y270 度swapped-x-y inverted-y这个表格是我在实际项目中总结的不一定适用于所有屏幕但可以作为起点再根据实际触摸效果微调。5.4 调试过程中的独家避坑技巧第一个技巧在设备树里给 GT911 节点加wakeup-source属性可以让触摸屏唤醒系统但如果你不需要这个功能千万别加否则系统休眠时触摸中断会频繁唤醒耗电飞快。第二个技巧ts_calibrate生成的pointercal文件最好备份因为每次重新校准都会覆盖。如果校准后效果不如之前可以恢复备份。第三个技巧如果 I2C 总线上挂了多个设备确保 GT911 的地址不冲突。我遇到过 I2C3 上同时挂了 GT911 和另一个传感器地址都是 0x5d结果两个设备互相干扰。解决办法是改其中一个的地址或者换一条 I2C 总线。第四个技巧调试初期可以在dmesg里加ignore_loglevel内核参数让所有日志都打印到控制台方便实时观察驱动加载过程。6. 从驱动到应用完整链路验证6.1 用 evtest 和 ts_test 做端到端测试驱动和 tslib 都配好之后我习惯用两个工具做最终验证。evtest看原始数据确认坐标范围和触摸点数。ts_test看校准后的数据确认坐标映射正确。ts_test有两个模式ts_test直接画点ts_test --linear用校准矩阵转换。如果ts_test画出的点和手指位置一致说明整条链路都通了。6.2 Qt 应用下的触摸配置要点Qt 应用如果走 tslib需要设置QT_QPA_GENERIC_PLUGINStslib:/dev/input/event2并且确保TSLIB_TSDEVICE环境变量在 Qt 启动前已经导出。如果 Qt 用的是 evdev 插件则需要设置QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS/dev/input/event2:rotate90之类的参数。两种方式选一种就行不要混用否则会出现双重校准或者坐标错乱。6.3 性能与稳定性观察GT911 的报点率一般是 100Hz 左右足够日常使用。如果发现触摸卡顿可以检查 I2C 频率是否被降到了 100kHz或者中断是否被其他设备共享导致延迟。cat /proc/interrupts看中断分布如果 GT911 的中断和其他设备共享同一个 IRQ 号可能会互相影响。RK3568 的 GPIO 中断一般可以独立分配尽量让 GT911 独占一个中断号。稳定性方面我连续跑了 72 小时的老化测试触摸没有丢点或者漂移。唯一遇到的问题是系统休眠唤醒后GT911 偶尔不工作后来发现是休眠时复位引脚被拉低唤醒后没有重新初始化。解决办法是在驱动的resume回调里重新走一遍复位时序或者干脆在设备树里禁用休眠功能。这个项目后续还可以扩展的地方很多比如把校准参数写到 EEPROM 里实现免校准或者用 libinput 替代 tslib适配 Wayland 环境。但就目前这套方案而言它在 RK3568 上已经足够稳定成本也低适合批量出货的工业产品。
返回列表