拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

GT911触摸芯片调试全攻略:从设备树配置到tslib校准

GT911触摸芯片调试全攻略:从设备树配置到tslib校准 GT911 这颗触摸芯片做嵌入式的人大概率都碰过。它便宜、供货稳、I2C 接口简单从国产平板到工控一体机到处都能见到它的身影。但真到调试阶段很多人会卡在几个地方设备树里中断脚和复位脚配反了、I2C 地址搞不清楚是 0x5D 还是 0x14、上电时序没对上导致 probe 失败、好不容易驱动起来了触摸坐标又是反的、最后还要面对 tslib 校准这一关。我前后在 RK3568 和几款全志平台上都调过 GT911每次都会遇到点新花样索性把整个流程完整梳理一遍从设备树配置一直写到 tslib 校准把中间那些文档里不会写的坑都摊开讲。这篇内容适合正在调 GT911 的驱动工程师、做 Linux 触摸屏适配的 BSP 同学以及需要把触摸屏跑通再交给上层应用开发的同行。我会按实际调试顺序来组织先搞清楚 GT911 的硬件特性和上电时序再动手写设备树然后验证驱动 probe接着处理坐标方向问题最后用 tslib 做校准并验证。每一步都会说明为什么这么做以及我踩过的具体坑。1. GT911 上电之前必须搞清楚的硬件特性1.1 这颗芯片到底特殊在哪GT911 是汇顶的一颗电容触摸控制芯片支持最多 5 点触控通过标准 I2C 接口和主控通信。它和很多触摸芯片不一样的地方在于I2C 从地址不是固定的而是由上电时 INT 和 RST 两个引脚的电平组合决定的。这一点是后面所有配置问题的根源必须先讲清楚。具体来说GT911 在复位释放的瞬间会锁存 INT 引脚的电平根据这个电平决定自己用哪个地址INT 引脚状态复位释放时I2C 从地址低电平0x5D高电平0x14这意味着如果你设备树里写的地址和实际上电时序决定的地址对不上驱动 probe 时读到的就是一堆 0xFF 或者直接 NACK根本进不去。我见过太多人在这里卡半天反复检查设备树地址其实问题出在复位时序上。1.2 上电时序为什么这么关键GT911 的上电时序要求比较严格官方 datasheet 里给的是VDD 和 VDDIO 上电后RST 需要保持低电平至少 10ms然后 INT 引脚在 RST 拉高之前要先设置好目标地址对应的电平RST 拉高后至少延时 55ms 才能开始 I2C 通信。这个顺序如果乱了芯片要么不响应要么锁存到错误的地址。实际调试中最容易出问题的是 INT 和 RST 的先后顺序。很多参考设计的原理图上INT 和 RST 是接到主控的两个 GPIO 上的但如果你在设备树里把这两个 GPIO 的顺序写反了或者驱动里操作顺序不对芯片就会锁存到非预期的地址。我的建议是先确认原理图上 INT 和 RST 分别接的是哪个 GPIO然后在设备树里严格按照 datasheet 的时序来配置。1.3 中断引脚和复位引脚的电气特性GT911 的 INT 引脚是开漏输出需要外部上拉电阻典型值是 10K。RST 引脚是输入内部有下拉但为了时序稳定一般也会在外面加一个 10K 上拉到 VDDIO。这两个电阻如果漏贴或者阻值不对会出现时好时坏的现象——有时候能 probe 成功有时候又不行非常折磨人。另外要注意的是GT911 的 VDDIO 电压范围是 1.8V 到 3.3V要和主控的 I2C 电平匹配。如果主控 I2C 是 3.3V 而 GT911 的 VDDIO 接的是 1.8V虽然 I2C 是开漏的理论上可以电平转换但实际波形可能会因为上拉电阻和线容导致上升沿变缓高速通信时容易出错。我一般建议 VDDIO 和主控 I2C 电压保持一致省去很多麻烦。2. 设备树配置从引脚定义到 I2C 节点2.1 先确认硬件连接再动手写在写设备树之前必须先把硬件连接确认清楚。需要确认的信息包括GT911 挂在哪个 I2C 控制器上、INT 接的是哪个 GPIO、RST 接的是哪个 GPIO、供电是常电还是可控电源。这些信息从原理图上都能查到但很多人跳过这一步直接抄参考设备树结果引脚对不上调半天。以 RK3568 为例假设 GT911 挂在 I2C3 上INT 接 GPIO3_B5RST 接 GPIO3_B6供电是常电 3.3V。那么设备树里需要做两件事一是在 I2C3 节点下添加 GT911 的子节点二是配置 pinctrl 把这两个 GPIO 设置为正确的功能。2.2 I2C 子节点的完整写法下面是一个经过验证的 GT911 设备树节点我加了详细注释说明每个属性的作用i2c3 { status okay; clock-frequency 400000; /* GT911 支持 400K但调试阶段建议先用 100K */ gt911: gt9115d { compatible goodix,gt911; reg 0x5d; /* 地址由 INT 引脚复位时的电平决定低电平为 0x5d */ interrupt-parent gpio3; interrupts RK_PB5 IRQ_TYPE_EDGE_FALLING; /* INT 引脚下降沿触发 */ reset-gpios gpio3 RK_PB6 GPIO_ACTIVE_LOW; /* RST 引脚低电平复位 */ irq-gpios gpio3 RK_PB5 GPIO_ACTIVE_HIGH; /* INT 引脚用于控制地址锁存 */ pinctrl-names default; pinctrl-0 gt911_int_rst; touchscreen-size-x 1024; touchscreen-size-y 600; touchscreen-inverted-x; touchscreen-inverted-y; status okay; }; };这里有几个点需要展开说。reg属性的值取决于你的上电时序设计如果你在复位释放时把 INT 拉低那地址就是 0x5D如果拉高就是 0x14。我一般习惯用 0x5D因为很多参考驱动默认就是这个地址。interrupts属性里我用了IRQ_TYPE_EDGE_FALLING因为 GT911 的中断是低电平有效配置成下降沿触发比较稳妥。有些驱动会要求配置成IRQ_TYPE_LEVEL_LOW这个要看具体驱动实现如果中断一直触发或者不触发可以在这两个之间切换试试。irq-gpios这个属性不是所有驱动都支持但我在实际调试中发现在驱动 probe 阶段手动控制 INT 引脚来锁存地址是非常必要的。因为内核启动过程中GPIO 的默认状态可能不确定如果不主动控制芯片可能锁存到错误的地址。2.3 pinctrl 配置的细节pinctrl 节点需要把 INT 和 RST 两个引脚都配置好pinctrl { gt911 { gt911_int_rst: gt911-int-rst { rockchip,pins 3 RK_PB5 RK_FUNC_GPIO pcfg_pull_up, /* INT 上拉 */ 3 RK_PB6 RK_FUNC_GPIO pcfg_pull_up; /* RST 上拉 */ }; }; };注意这里两个引脚都配置了上拉。INT 上拉是因为它是开漏输出需要外部上拉RST 上拉是为了保证默认状态下复位是释放的避免芯片一直处于复位状态。有些平台 pinctrl 的写法不太一样比如全志平台用的是function和pins分开写的方式但核心思路是一样的。2.4 供电节点的处理如果 GT911 的供电是可控的比如通过一个 GPIO 控制的 LDO那还需要在设备树里添加 regulator 节点并在 GT911 节点里引用它。这一步很多人会忽略导致驱动 probe 时芯片还没上电自然读不到 ID。gt911_vdd: gt911-vdd { compatible regulator-fixed; regulator-name gt911_vdd; regulator-min-microvolt 3300000; regulator-max-microvolt 3300000; gpio gpio0 RK_PC0 GPIO_ACTIVE_HIGH; enable-active-high; regulator-always-on; /* 调试阶段先设为常开排除供电时序问题 */ };调试阶段我建议先设成regulator-always-on等驱动跑通了再改成按需使能。这样可以排除供电时序带来的干扰把问题范围缩小。3. 驱动 probe 失败时的排查链路3.1 先看内核日志里有没有 I2C 通信驱动 probe 失败最直接的表现就是/dev/input/eventX设备节点不存在或者dmesg里有 GT911 相关的报错。第一步永远是看日志dmesg | grep -i gt911 dmesg | grep -i i2c3如果看到gt911 3-005d: gt911_read_id failed或者i2c i2c-3: sendbytes: NAK bailout这类信息说明 I2C 通信本身就没通。这时候不要急着改驱动先确认硬件层面的事情。3.2 用 i2cdetect 确认芯片是否在总线上在驱动加载之前可以先手动扫描 I2C 总线看看 GT911 是否响应i2cdetect -y 3如果 0x5D 位置显示的是5d说明芯片在总线上并且地址正确。如果显示的是--说明芯片没有响应可能的原因包括供电没上、复位没释放、地址锁存错误、I2C 线路有问题。如果显示的是UU说明地址被驱动占用了这是正常的。我遇到过一次特别诡异的情况i2cdetect能看到 0x5D但驱动 probe 就是失败。后来发现是驱动里读 ID 的时序太快芯片还没准备好就发了读命令。解决办法是在 probe 函数里读 ID 之前加一个 100ms 的延时等芯片内部初始化完成。3.3 地址锁存错误的典型表现和修复地址锁存错误的表现很有特点i2cdetect在 0x5D 和 0x14 两个位置都扫不到或者只有一个能扫到但和预期不符。这时候需要检查上电时序。我的做法是在驱动 probe 的早期阶段手动控制 INT 和 RST 引脚模拟一次完整的复位时序/* 拉低 RST */ gpiod_set_value_cansleep(reset_gpio, 0); msleep(10); /* 设置 INT 电平决定地址这里设为低电平选择 0x5D */ gpiod_set_value_cansleep(irq_gpio, 0); msleep(1); /* 释放 RST */ gpiod_set_value_cansleep(reset_gpio, 1); msleep(60); /* 将 INT 配置为中断模式 */ gpiod_direction_input(irq_gpio);这段时序的关键是RST 拉低至少 10msINT 电平在 RST 释放前设置好RST 释放后至少等 55ms 再通信。这三个时间参数如果有一个不满足就可能锁存失败。3.4 中断不触发的排查驱动 probe 成功了设备节点也有了但触摸没反应这种情况多半是中断没触发。排查步骤用cat /proc/interrupts | grep gt911确认中断号是否注册成功触摸屏幕时观察中断计数是否增加如果不增加用万用表或者示波器量 INT 引脚看触摸时是否有电平变化如果有电平变化但中断计数不增加检查设备树里中断触发方式是否配置正确我遇到过 INT 引脚被其他驱动占用的情况导致 GT911 的中断注册失败。这时候需要检查 pinctrl 里有没有其他节点也引用了同一个 GPIO。4. 坐标方向不对先别急着改驱动4.1 坐标问题的三种典型表现触摸驱动跑通之后坐标问题几乎一定会遇到。常见的有三种X 轴反向、Y 轴反向、XY 交换。这三种问题的根源不同处理方式也不一样。X 轴或 Y 轴反向通常是屏幕的物理安装方向和触摸屏的坐标系不一致导致的。比如屏幕旋转了 180 度那 X 和 Y 都需要反向。XY 交换则通常是屏幕旋转了 90 度或 270 度。4.2 优先在设备树里解决GT911 的驱动支持通过设备树属性来调整坐标方向不需要改驱动代码touchscreen-inverted-x; /* X 轴反向 */ touchscreen-inverted-y; /* Y 轴反向 */ touchscreen-swapped-x-y; /* XY 交换 */这三个属性可以组合使用。比如屏幕旋转 180 度就同时加touchscreen-inverted-x和touchscreen-inverted-y旋转 90 度就加touchscreen-swapped-x-y再加上其中一个 inverted 属性。我的经验是先在设备树里试不要一上来就改驱动。因为设备树属性是标准化的改起来快而且不会引入代码 bug。只有设备树属性解决不了的情况才考虑改驱动。4.3 用 evtest 验证坐标调整完设备树属性后用evtest工具验证坐标是否正确evtest /dev/input/event2然后在屏幕上点四个角和中心观察输出的 ABS_X 和 ABS_Y 值。如果左上角对应 (0,0)右下角对应 (max_x, max_y)说明方向正确。如果某个角的值不对根据实际输出调整设备树属性。这里有个小技巧先点左上角和右下角确定 X 和 Y 的范围再点右上角和左下角确定方向。这样比盲目点一堆点效率高得多。4.4 屏幕旋转和触摸坐标的联动如果系统里屏幕做了旋转比如通过 DRM 的 rotation 属性触摸坐标也需要做相应的旋转。这时候光靠设备树属性可能不够因为屏幕旋转是运行时决定的。这种情况下通常需要在应用层或者通过 udev 规则来做坐标变换。我在 RK3568 上遇到过竖屏改横屏的需求屏幕通过 DRM 旋转了 90 度触摸坐标也需要跟着转。最后是在 tslib 的配置里做了坐标变换具体方法在下一节讲。5. tslib 校准从编译到生成校准文件5.1 tslib 到底解决了什么问题很多人会问驱动已经把坐标报上来了为什么还要 tslib原因是触摸屏的物理坐标和 LCD 的像素坐标之间不是完美对应的存在偏移和缩放。tslib 的作用就是通过校准建立一个从触摸原始坐标到屏幕像素坐标的映射关系。tslib 的校准原理是在屏幕上显示几个校准点让用户依次点击然后根据点击的原始坐标和理论坐标计算出一个变换矩阵。这个矩阵会被保存到校准文件里后续触摸事件都会经过这个矩阵变换。5.2 交叉编译 tslibtslib 需要交叉编译到目标平台。以 RK3568 的 aarch64 工具链为例./autogen.sh ./configure --hostaarch64-linux-gnu \ --prefix/usr/local/tslib \ --enable-staticno \ --disable-hw-support make -j$(nproc) make install--disable-hw-support这个选项可以关掉一些不需要的硬件支持模块减小体积。编译完成后把/usr/local/tslib目录拷贝到目标板的对应位置。5.3 配置 tslib 环境变量tslib 运行需要几个环境变量通常写在/etc/profile或者启动脚本里export TSLIB_TSDEVICE/dev/input/event2 export TSLIB_CALIBFILE/etc/pointercal export TSLIB_CONFFILE/usr/local/tslib/etc/ts.conf export TSLIB_PLUGINDIR/usr/local/tslib/lib/ts export TSLIB_CONSOLEDEVICEnone export TSLIB_FBDEVICE/dev/fb0 export LD_LIBRARY_PATH/usr/local/tslib/lib:$LD_LIBRARY_PATHTSLIB_TSDEVICE要指向 GT911 对应的 event 设备。如果不确定是哪个 event可以用cat /proc/bus/input/devices查看找到 GT911 对应的 event 号。5.4 运行校准程序环境变量配好后运行ts_calibratets_calibrate屏幕上会出现五个校准点依次点击。点击完成后会在TSLIB_CALIBFILE指定的路径生成校准文件。如果校准过程中某个点没点准可以重新运行。校准完成后用ts_test验证ts_testts_test会显示触摸轨迹如果轨迹和手指移动一致说明校准成功。如果轨迹偏移或者抖动可能需要重新校准或者检查ts.conf里的滤波配置。5.5 ts.conf 的滤波配置ts.conf控制 tslib 的插件加载和滤波策略。默认配置可能不够好我一般会调整成module_raw input module pthres pmin1 module variance delta30 module dejitter delta100 module linearpthres是压力阈值variance是方差滤波dejitter是去抖。这几个参数需要根据实际触摸效果调整。如果触摸抖动厉害可以增大dejitter的 delta 值如果触摸不灵敏可以减小pthres的 pmin 值。6. 那些文档里不会写的调试心得6.1 上电时序用示波器抓一次比什么都强我强烈建议在第一次调试 GT911 时用示波器抓一下 RST、INT、VDD 和 SDA/SCL 的波形。很多问题从波形上一眼就能看出来比如 RST 释放太快、INT 电平在 RST 释放时还在跳变、I2C 上拉不够导致上升沿太缓。这些细节用万用表是看不出来的但恰恰是导致 probe 失败的常见原因。抓波形的触发点设在 RST 的上升沿然后观察 INT 在 RST 上升沿前后的电平状态。如果 INT 在 RST 上升沿时不是稳定的低电平或高电平那地址锁存就会有问题。6.2 I2C 速率不要一上来就 400KGT911 支持 400K 的 I2C 速率但调试阶段我建议先用 100K。因为 100K 对时序和上拉的要求更低更容易跑通。等驱动稳定了再改成 400K 提升响应速度。如果 400K 下出现偶发的通信失败多半是上拉电阻偏大或者走线太长导致的可以适当减小上拉电阻到 4.7K 试试。6.3 中断触发方式要匹配实际波形GT911 的中断是低电平有效但配置成IRQ_TYPE_EDGE_FALLING还是IRQ_TYPE_LEVEL_LOW要看具体驱动。有些驱动在中断处理里会读寄存器清除中断这种情况下用边沿触发更合适有些驱动依赖电平触发那就必须配成电平触发。如果中断一直触发导致 CPU 占用率高多半是触发方式配错了。6.4 校准文件要持久化保存ts_calibrate生成的校准文件默认保存在/etc/pointercal但如果根文件系统是只读的或者重启后丢失就需要把校准文件保存到可持久化的分区并在启动时恢复。我一般会把校准文件放到/data分区然后在启动脚本里做一个软链接或者拷贝。6.5 多点触控和 tslib 的兼容性tslib 对多点触控的支持有限它主要是为单点触摸设计的。如果你的应用需要多点触控建议直接用 evdev 或者 libinput不要走 tslib。tslib 更适合单点触摸的工控场景比如电阻屏或者只需要单点操作的电容屏。7. 从驱动到应用的完整验证流程7.1 分层验证的思路调试触摸屏最忌讳的就是一上来就跑应用出了问题不知道是哪一层的问题。我的做法是分层验证先验证 I2C 通信再验证驱动 probe然后验证中断接着验证坐标最后验证 tslib 校准。每一层都确认没问题了再往上走。具体来说I2C 层用i2cdetect验证驱动层用dmesg和/proc/bus/input/devices验证中断层用/proc/interrupts验证坐标层用evtest验证校准层用ts_test验证。这个顺序不能乱乱了就会浪费很多时间。7.2 一个完整的验证脚本我把常用的验证命令整理成了一个脚本每次调试新板子的时候直接跑一遍#!/bin/bash echo I2C 设备扫描 i2cdetect -y 3 echo GT911 驱动日志 dmesg | grep -i gt911 echo 输入设备列表 cat /proc/bus/input/devices | grep -A 5 -i gt911 echo 中断统计 cat /proc/interrupts | grep -i gt911 echo tslib 环境变量 env | grep TSLIB这个脚本能快速给出当前状态的全貌省去一条条敲命令的时间。7.3 常见问题速查表现象可能原因排查方法i2cdetect 扫不到设备供电未上、复位未释放、地址锁存错误检查供电和复位引脚电平用示波器抓上电时序probe 失败读 ID 错误I2C 通信失败、地址不对、时序太快降低 I2C 速率检查设备树地址加延时设备节点存在但无触摸中断未触发、中断配置错误检查 /proc/interrupts用示波器量 INT 引脚坐标反向或交换屏幕安装方向与触摸坐标系不一致调整设备树 inverted 和 swapped 属性触摸抖动或跳点滤波参数不合适、电源噪声调整 ts.conf 滤波参数检查电源纹波校准后仍有偏移校准点未点准、校准文件未保存重新校准检查校准文件路径和权限这张表是我在实际调试中总结出来的覆盖了 90% 以上的常见问题。遇到问题时先查表能快速定位方向。7.4 关于 GT911 的固件更新GT911 支持通过 I2C 更新固件汇顶提供了相应的工具。但我的建议是除非必要不要轻易更新固件。因为固件更新有风险一旦失败芯片可能变砖。而且大多数情况下驱动层面的问题不需要通过更新固件来解决。如果确实需要更新一定要先备份原始固件并确保供电稳定。固件更新通常是通过写入特定的寄存器序列来触发的具体流程参考汇顶的官方文档。更新完成后需要重新上电并重新校准。8. 不同平台上的差异和注意事项8.1 RK3568 平台的特殊处理RK3568 的 I2C 控制器在设备树里的节点名是i2c3这种形式pinctrl 的写法是rockchip,pins。RK3568 的 GPIO 有多个 bank每个 bank 有 32 个引脚引用的时候要注意 bank 号和引脚号的对应关系。另外 RK3568 的 I2C 时钟频率配置在clock-frequency属性里默认是 100K可以改成 400K。RK3568 上还有一个坑如果 I2C 控制器被其他驱动占用比如被配置成了其他功能需要先确认status是okay并且 pinctrl 没有冲突。8.2 全志平台上的差异全志平台的 pinctrl 写法和 RK3568 不太一样用的是function和pins分开定义的方式。I2C 节点的命名也不同通常是twi3这种形式。全志的 GPIO 编号方式也和 RK3568 不同需要查对应的 datasheet。在全志平台上调试 GT911 时我遇到过 I2C 控制器默认速率是 400K 的情况导致通信不稳定。后来在设备树里显式指定了clock-frequency 100000才稳定下来。8.3 通用注意事项不管在哪个平台上有几个原则是通用的第一先确认硬件连接再写设备树第二调试阶段先用低速 I2C第三上电时序一定要用示波器验证第四坐标问题优先在设备树里解决第五tslib 校准文件要持久化。还有一点不同版本的 GT911 固件在寄存器定义上可能有细微差异如果遇到驱动读 ID 正常但功能异常的情况可以对比一下固件版本。不过这种情况比较少见大多数问题还是出在配置和时序上。9. 写在最后的一些个人体会调 GT911 这几年最大的感受就是硬件问题永远比软件问题更难查但也更值得花时间查。我见过太多人一遇到 probe 失败就开始改驱动代码改了半天发现是硬件上拉电阻没贴。所以我的习惯是任何触摸屏调试第一步永远是确认硬件第二步是抓波形第三步才是看驱动。另外设备树配置虽然看起来简单但每一个属性背后都有它的道理。比如irq-gpios这个属性很多人不知道它是干什么的其实它就是在驱动 probe 阶段用来控制 INT 引脚锁存地址的。理解了这一点就不会随便删掉这个属性了。tslib 校准这块我的建议是不要怕麻烦每次换屏幕或者换结构件都重新校准一次。因为触摸屏的物理特性和安装方式都会影响坐标映射用旧的校准文件可能不准。校准的时候尽量用手指或者电容笔的正常使用姿势来点不要用指甲尖去戳那样点出来的坐标和实际使用会有偏差。最后说一个我最近才发现的细节GT911 在低温环境下比如零下 10 度触摸灵敏度会下降这是电容屏的通病。如果产品有低温使用场景可能需要在固件层面调整灵敏度参数或者选用支持低温的型号。这个在 datasheet 里不会写但实际项目中会遇到。
返回列表