# gt911开发文档 **Repository Path**: a-flying-panda/gt911-development-document ## Basic Information - **Project Name**: gt911开发文档 - **Description**: gt911开发文档 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2024-11-18 - **Last Updated**: 2025-12-18 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ### 地址配置 0x28是往右移一位后的设备地址,实际的设备地址是0x14,我们的设备树配置是0x14,所以我们要按照图中的0x28的地址去配置。 ![alt](2.png) ![alt](1.png) linux驱动程序中设置寄存器地址的方法是控制两个IO电平 ```c /* 4、初始化GT9147,要严格按照GT9147时序要求 */ gpio_set_value(dev->irq_pin, 1); /* 拉高INT引脚 */ gpio_set_value(dev->reset_pin, 0); /* 复位GT9147 */ msleep(10); gpio_set_value(dev->reset_pin, 1); /* 停止复位GT9147 */ msleep(10); gpio_set_value(dev->irq_pin, 0); /* 拉低INT引脚 */ msleep(50); ``` --- ### 问题:GT911触控芯片,中断引脚初始化后,自动重复的进入中断 原因:没有在中断处理函数中对GT911的寄存器0X814E写0。寄存器0X814是触摸屏被触摸标志。 寄存器说明如下所示: [0x814E]: Bit7: Buffer status,1 表示坐标(或按键)已经准备好,主控可以读取;0 表示未就绪,数据无效。 当主控读取完坐标后,必须通过 I2C 将此标志(或整个字节)写为 0。 Bit4: HaveKey, 1 表示有按键,0 表示无按键(已经松键)。 Bit3~0: Number of touch points, 屏上的坐标点个数 ```c data = 0x00; /* 向0X814E寄存器写0 */ gt9147_write_regs(dev, GT_GSTID_REG, &data, 1); ``` --- 其实内核里面是自带gt911驱动代码的,在kernel/drivers/input/touchscreen目录下,这里面有很多触摸屏的驱动代码 ![image-20241118172044113](3.png) 这里有很多驱动代码,但我们并不是所有都需要,所以需要裁剪,裁剪使用命令: ```shell export ARCH=arm make menuconfig ``` 注意:需要在内核源码目录下使用. ![image-20241118172623790](4.png) 参考:[8.认识输入子系统源码以及裁剪_哔哩哔哩_bilibili](https://www.bilibili.com/video/BV1Gg4y1X7fS?spm_id_from=333.788.videopod.episodes&vd_source=a7d8b8520fbd7ef0d76678c37e01e9e0&p=8) --- > 为什么使用devm_request_threaded_irq这个函数? 没有使用 request_irq函数申请中断,而是采用了 devm_request_threaded_irq 这个函数,为什么使用这个函数呢?是 不是 request_irq 函数不能使用?答案肯定不是的,这里用 request_irq 函数是绝对没问题的。那 为何要用 devm_request_threaded_irq 呢?这里我们就简单的介绍一下这个 API 函数, devm_request_threaded_irq 函数特点如下 ①、用于申请中断,作用和 request_irq 函数类似。 ②、此函数的作用是中断线程化,大家如果直接在网上搜索“devm_request_threaded_irq” 会发现相关解释很少。但是大家去搜索 request_threaded_irq 函数就会有很多讲解的博客和帖子, 这两个函数在名字上的差别就是前者比后者多了个“devm_”前缀,“devm_”前缀稍后讲解。 大家应该注意到了“request_threaded_irq”相比“request_irq”多了个 threaded 函数,也就是线 程的意思。那么为什么要中断线程化呢?我们都是知道硬件中断具有最高优先级,不论什么时 候只要硬件中断发生,那么内核都会终止当前正在执行的操作,转而去执行中断处理程序(不考 虑关闭中断和中断优先级的情况),如果中断非常频繁的话那么内核将会频繁的执行中断处理程 序,导致任务得不到及时的处理。中断线程化以后中断将作为内核线程运行,而且也可以被赋 予不同的优先级,任务的优先级可能比中断线程的优先级高,这样做的目的就是保证高优先级 的任务能被优先处理。大家可能会疑问,前面不是说可以将比较耗时的中断放到下半部(bottom half)处理吗?虽然下半部可以被延迟处理,但是依旧先于线程执行,中断线程化可以让这些比 较耗时的下半部与进程进行公平竞争。 要注意,并不是所有的中断都可以被线程化,重要的中断就不能这么操作。对于触摸屏而 言只要手指放到屏幕上,它可能就会一直产生中断(视具体芯片而定,GT911 是这样的),中断 处理程序里面需要通过 I2C 读取触摸信息并上报给内核,I2C 的速度最大只有 400KHz,算是低 速外设。不断的产生中断、读取触摸信息、上报信息会导致处理器在触摸中断上花费大量的时 间,但是触摸相对来说不是那么重要的事件,因此可以将触摸中断线程化。如果你觉得触摸中 断很重要,那么就可以不将其进行线程化处理。总之,要不要将一个中断进行线程化处理是需 要自己根据实际情况去衡量的。linux 内核自带的 goodix.c(汇顶科技)、mms114.c(MELFAS 公司)、 zforce_ts.c(zForce 公司)等多点电容触摸 IC 驱动程序都采用了中断线程化,当然也有一些驱动 没有采用中断线程化。 ③、最后来看一下“devm_”前缀,在 linux 内核中有很多的申请资源类的 API 函数都有对 应的“devm_”前缀版本。比如 devm_request_irq 和 request_irq 这两个函数,这两个函数都是申 请中断的,我们使用 request_irq 函数申请中断的时候,如果驱动初始化失败的话就要调用 free_irq 函数对申请成功的 irq 进行释放,卸载驱动的时候也需要我们手动调用 free_irq 来释放 irq。假如我们的驱动里面申请了很多资源,比如:gpio、irq、input_dev,那么就需要添加很多 goto 语句对其做处理,当这样的标签多了以后代码看起来就不整洁了。“devm_”函数就是为了 处理这种情况而诞生的,“devm_”函数最大的作用就是: 使用“devm_”前缀的函数申请到的资源可以由系统自动释放,不需要我们手动处理。 如果我们使用 devm_request_threaded_irq 函数来申请中断,那么就不需要我们再调用 free_irq 函数对其进行释放。大家可以注意一下,带有“devm_”前缀的都是一些和设备资源管 理有关的函数。关于“devm_”函数的实现原理这里就不做详细的讲解了,我们的重点在于学会 如何使用这些 API 函数,感兴趣的可以查阅一些其他文档或者帖子来看一下“devm_”函数的 实现原理。 --- 纯参考正点原子的 ---