正点原子Linux C应用编程:移植tslib并使其适配7寸LCD1024*600的GT911触摸驱动
作者在学习【正点原子】I.MX6U嵌入式Linux C应用编程指南V1.4时,发现移植tslib后,触摸事件触发不正常。
使用的硬件版本:正点原子 I.MX6U ALPHA V2.4版本底板,LCD:正点原子7寸1024*600,型号ATK-MD0700R-1024600
问题描述与解决过程
教程中老师使用的屏幕是ft5x06驱动,查看本屏幕使用的是goodix汇顶公司的gt911,由于linux内核为笔者自行移植,故无gt的驱动,需要自行添加
1. 先将开发板光盘目录下定位到以下目录
例程源码-出厂源码-linux内核源码-drivers/input/touchscreen/gt9xx.c、gt9xx.h
复制这两个文件,放到自己的linux内核的同目录中
2. 编辑Kconfig文件。把驱动加到内核菜单中
vim drivers/input/touchscreen/Kconfig
打开Kconfig,如果没有vim就使用vi、nano:350
定位到350行
将如下的内容添加
config TOUCHSCREEN_GT9XXtristate "GT9XX I2C touchscreen"depends on I2ChelpSay Y here if you have the GT9XX touchscreen connected to yoursystem.If unsure, say N.To compile this driver as a module, choose M here: themodule will be called gt9xx.
切记,一定要对齐,参考上下文的格式,Kconfig
对格式的检查很严格,否则在编译的时候会报错。
这让我想起了之前编辑linux内核某些c文件时,使用双斜杠//
注释会导致编译器报错,同时在for循环中定义变量也是从 C99 标准开始引入的.
在 C 语言中,
//
用于单行注释,这是从 C99 标准开始引入的。C99 之前的版本,如 C90(也称为 ANSI C 或 ISO C90),只支持多行注释,即使用/*
开始和*/
结束的注释。
所以在修改代码的时候一定要关注内核使用的编译器编译时遵循的具体语言标准!
Kconfig
是 Linux 内核配置系统的一部分,它用于在构建内核时选择要编译的配置选项。Kconfig
文件包含了内核中各种特性、驱动程序和子系统的配置选项,允许开发者根据需要选择启用或禁用特定的功能。
只有配置了Kconfig
中GT芯片的部分,在内核目录下执行make menuconfig
才能在模块的编译选项中选择把对应的模驱动编译进内核
下面是对上面Kconfig
代码的具体解释
config TOUCHSCREEN_GT9XX
:这是配置项的名称,TOUCHSCREEN_GT9XX
是该配置项的标识符。tristate "GT9XX I2C touchscreen"
:这定义了配置项的类型为三态(tristate),意味着该选项可以被设置为 Y(是,内置于内核)、M(模块,作为可加载模块)、N(否,不编译)。depends on I2C
:这表示该配置项依赖于 I2C 配置项。如果 I2C 没有被选中,这个触摸屏驱动的配置项也不会出现。help
:这是帮助文本,为开发者提供了关于该配置项的额外信息。- 如果你的系统中连接了 GT9XX 触摸屏,请在这里选择 Y。
- 如果你不确定,在这里选择 N。
- 如果你想将这个驱动编译为一个模块,请在这里选择 M。编译后的模块将被称为
gt9xx
。
添加后大概是这样的:
3. 编辑Makefile文件
vim drivers/input/touchscreen/Makefile
添加如下代码
obj-$(CONFIG_TOUCHSCREEN_GT9XX) += gt9xx.o
含义和作用如下:
obj-$(CONFIG_TOUCHSCREEN_GT9XX)
:条件语句,检查内核配置中是否定义了CONFIG_TOUCHSCREEN_GT9XX
宏。这个宏在内核配置菜单中设置,用于决定是否包含 GT9XX 触摸屏驱动。+=
:这个操作符用于向变量obj
添加新的对象文件。如果条件语句为真(即CONFIG_TOUCHSCREEN_GT9XX
被设置为y
或m
),则执行+=
操作。gt9xx.o
:编译对象文件名。如果CONFIG_TOUCHSCREEN_GT9XX
启用,gt9xx.o
将被添加到obj
变量中,它将被编译并包含在最终的内核或模块中。
在内核构建过程中,make menuconfig
、make xconfig
或 make nconfig
命令会生成一个 .config
文件,其中包含了所有配置选项的设置。CONFIG_TOUCHSCREEN_GT9XX
就是其中的一个选项,它在配置菜单的“Device Drivers” -> “Input device support” -> “Touchscreen devices”下。
如果你选择了该选项(设置为 y
表示直接编译进内核,或 m
表示编译为模块),那么 Makefile
中的这行代码就会生效,gt9xx.o
将被编译并包含在内核或模块中。如果没有选择,那么 CONFIG_TOUCHSCREEN_GT9XX
将不被定义,这行代码也不会有任何效果。
menuconfig只是充当了一个有着交互界面的宏开关配置器,Makefile才真正决定具体编译内容,是构建系统的核心
4. 修改menuconfig
执行make menuconfig
,进入以下层级,选中GT9XX I2C touchscreen这个宏,为*星号,编译进内核
- 编译进内核 (Y/*):该驱动或功能被编译为内核的一部分,在启动时自动加载。意味着该功能或驱动程序将始终可用,会增加内核的大小和启动时间。适用于那些始终需要并且对启动时间不敏感的驱动程序。
- 编译为模块 (M):该驱动或功能被编译为一个单独的模块(
.ko
文件),在需要时通过modprobe
命令动态加载到内核中。这种方式允许系统管理员根据需要添加或移除功能,而不必重新编译整个内核。有助于保持内核的整洁和最小化,只有实际需要的模块才会被加载。
我们的触摸屏为了保证每次上电自动初始化,所以将他编译进内核。
5. 修改设备树
vim arch/arm/boot/dts/imx6ull-alientek-emmc.dts
在arch/arm/boot/dts/imx6ull-alientek-emmc.dts设备树i2c2节点下添加gt9xx的节点。
设备树是与硬件连接的通道,它指定了数据传输通过i2c2总线,gt911芯片i2c地址为0x5D,触摸事件的中断引脚和对应的中断号、复位引脚
goodix_ts@5d {compatible = "goodix,gt9xx";reg = <0x5d>;status = "okay";interrupt-parent = <&gpio1>;interrupts = <9 0>;pinctrl-0 = <&ts_int_pin&ts_reset_pin>;goodix,rst-gpio = <&gpio5 9 GPIO_ACTIVE_LOW>;goodix,irq-gpio = <&gpio1 9 GPIO_ACTIVE_LOW>;};
要检查gpio1 9有没有在其他地方被使用!
/&gpio1 9
该引脚被注册为中断,在芯片检测到有触摸活动会在这个引脚上发出低电平信号,通知CPU以最快的速度读取触摸的手指坐标
如果被其他设备占用,会产生问题。
在iomuxc节点下最后位置添加以下内容,复用为中断!!!:
ts_int_pin: ts_int_pin_mux {fsl,pins = <MX6UL_PAD_GPIO1_IO09__GPIO1_IO09 0x79>;};
在iomuxc_snvs节点下最后位置添加以下内容,这是复位管脚的复用:
ts_reset_pin: ts_reset_pin_mux {fsl,pins = <MX6ULL_PAD_SNVS_TAMPER9__GPIO5_IO09 0x79>;};
再检查一次,是否有管脚复用,若没有,执行make编译,拷贝zImage和dtb文件到tftpboot文件夹,上电启动
6. 验证
使用cat /proc/interrupts
验证中断号是否被成功注册
可以看到成功注册了中断
再根据【正点原子】I.MX6U嵌入式Linux C应用编程指南V1.4 第十八章 tslib库使用的步骤移植tslib,使用ts_print测试单点触摸,使用ts_test_mt可视化测试触摸屏是否正常!!!
[root@mygo]:~$:ts_print
7779.538104: 320 400 1
7779.551222: 320 400 1
7779.562483: 320 400 1
7779.574125: 318 399 1
7779.585729: 315 394 1
7779.597377: 310 385 1
7779.725341: 335 227 1
7779.736797: 348 215 1