触摸屏简介

GT911 是专为 7”~8”设计的新一代 5 点电容触控方案,拥有 26 个驱动通道和 14 个感应通道,
以满足更高的 touch 精度要求。
GT911 可同时识别 5 个触摸点位的实时准确位置,移动轨迹及触摸面积。并可根据主控需要,读取相应点数的触摸信息。

I2C 协议及 i2c 器件连接

每个连接到总线的器件都可使用软件根据它唯一的地址来识别,传输数据的设备之间是主从关系。

主机可做主机发送器或主机接收器;

多主机总线:两个或多个主机可同时发起数据传输,通过冲突检测及仲裁防止数据被破坏。

串行的 8 位双向数据传输。

主机:发起/停止数据传输,提供时钟信号的器件;

从机:被主机寻址的器件;

发送器:发送数据到总线的器件;

接收器:从总线接收数据的器件;

i2c 信号

S:SCL 高电平,SDA 由高到低跳变,开始传送数据;

P:SCL 高电平,SDA 由低到高跳变,结束传送数据;

transmitter 发送器 receiver 接收器;ACK:接收器在接收到 8 位数据后,在第 9 个时钟周期,拉低 SDA 电平;SDA 必须在 SCL 为高电平时有效,sda 数据必须在 SCL 为低电平下才可以发生变化;在第九个时钟是,主控会将 sda 拉高释放控制权,从设备收完数据后将 SDA 拉低,表示ack.

I2c 总线数据传输格式

发送到 SDA 总线上的每个字节必须是 8 位,每次传输可以发送的字节数量不受限制,每个字节后必须有一个响应位.先传输数据的高位(MSB).

GT9系列i2c接口有两个器件地址可用,我们用的是第一个0x5d:

配置触摸屏驱动

以友善电子的rk3399装的安卓系统为例;

打开系统配置菜单:

ron@ubuntu:~/work/rk3399-android-8.1$ cd kernel/ 
ron@ubuntu:~/work/rk3399-android-8.1/kernel$ make menuconfig

找到触摸屏Goodix GT9xx配置的Multi-touch Protocol A,取消选择、编译、重烧后,此屏幕触摸功能就会失效,原因是我们去掉了Goodix GT9xx的驱动程序。

 

 linux i2c子系统(框架)

软件框架简图:

硬件框架简图:

查找匹配的设备树节点

kernel/arch/arm64/boot/dts/rockchip$ grep -nir "goodix_ts" rk3399*

rk3399-nanopi4-common.dtsi:851: gt9xx: goodix_ts@5d {

i2c4:i2c编号为4的控制器节点,包含了goodix,gt9xx的从设备信息。

所以,i2c4在驱动加载时,顺便生成了goodix,gt9xx的从设备信息,并放入从设备总线上,等着自己写的驱动程序匹配(通过competible属性);

i2c驱动框架用到5个核心对象

 i2c驱动分层原理图:

i2c设备完成代码分析:

i2c子系统  工作原理分析

从两条主线入手

1.调用关系 如果贯穿?
应用
ret =read(fd, buf, sizeof(buf));//===========应用层
    |
    |
    sys_read
        |
        |
        gt9xx_read  //===========从设备驱动层
            |
            |
            ret = gtp_i2c_read(i2c_connect_client, buf, sizeof(buf));
                |
                |
                struct i2c_msg msgs[2];  //创建2个数据包对象
                msgs[0].flags = !I2C_M_RD; //写标志
                msgs[0].addr  = client->addr; //器件地址
                msgs[0].len   = GTP_ADDR_LENGTH;//16位地址
                msgs[0].buf   = &buf[0]; //存放寻址用地址的首地址
                msgs[1].flags = I2C_M_RD; //读标志
                msgs[1].addr  = client->addr; //器件地址
                msgs[1].len   = len - GTP_ADDR_LENGTH; //设置要读的字节数
                msgs[1].buf   = &buf[GTP_ADDR_LENGTH];//存放读出来的内容的首地址
                
                ret = i2c_transfer(client->adapter, msgs, 2);//将数据包交给底层函数进行收发数据包
                    |
                    |               //===================== i2c核心层       
                    ret = __i2c_transfer(adap, msgs, num);
                        |
                        |
                        for (ret = 0, try = 0; try <= adap->retries; try++) {
                            ret = adap->algo->master_xfer(adap, msgs, num);
                                    |  函数指针找不到定义
                                    | //======================???
                            
                        }
                    
2.分层  每层原理

2.1 适配器层

入口和出口函数被封装
module_platform_driver(rk3x_i2c_driver);

#define module_platform_driver(__platform_driver) \
    module_driver(__platform_driver, platform_driver_register, \
            platform_driver_unregister)

#define module_driver(__driver, __register, __unregister, ...) \
static int __init __driver##_init(void) \
{ \
    return __register(&(__driver) , ##__VA_ARGS__); \
} \
module_init(__driver##_init); \
static void __exit __driver##_exit(void) \
{ \
    __unregister(&(__driver) , ##__VA_ARGS__); \
} \
module_exit(__driver##_exit);

//创建平台驱动对象并初始化
static struct platform_driver rk3x_i2c_driver = {
    .probe   = rk3x_i2c_probe,
    .remove  = rk3x_i2c_remove,
    .driver  = {
        .name  = "rk3x-i2c",
        .of_match_table = rk3x_i2c_match,//匹配条件
        .pm = &rk3x_i2c_pm_ops,
    },
};

static const struct of_device_id rk3x_i2c_match[] = {
    。。。
    },
    {
        .compatible = "rockchip,rk3399-i2c",
        .data = (void *)&rk3399_soc_data
    },
    {},
};

struct rk3x_i2c {
    struct i2c_adapter adap;
    struct device *dev;
    
    wait_queue_head_t wait;
    。。。
};

//设备树节点和平台驱动匹配成功
static int rk3x_i2c_probe(struct platform_device *pdev)
    |
    struct device_node *np = pdev->dev.of_node; //拿节点对象
    struct rk3x_i2c *i2c;//本地结构体对象
    i2c = devm_kzalloc(&pdev->dev, sizeof(struct rk3x_i2c), GFP_KERNEL);//创建本地对象
    //初始化adapter对象
    strlcpy(i2c->adap.name, "rk3x-i2c", sizeof(i2c->adap.name));//i2c-4 名字
    i2c->adap.owner = THIS_MODULE;
    i2c->adap.algo = &rk3x_i2c_algorithm; //注册算法对象 i2c通信就可以调下去了
    i2c->adap.retries = 3;
    i2c->adap.dev.of_node = np;
    i2c->adap.algo_data = i2c;
    i2c->adap.dev.parent = &pdev->dev;
    //拿地址资源并IO映射
    mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    i2c->regs = devm_ioremap_resource(&pdev->dev, mem);
    if (IS_ERR(i2c->regs))
        return PTR_ERR(i2c->regs);
    //拿中断资源申请中断
    irq = platform_get_irq(pdev, 0);
    if (irq < 0) {
        dev_err(&pdev->dev, "cannot find rk3x IRQ\n");
        return irq;
    }

ret = devm_request_irq(&pdev->dev, irq, rk3x_i2c_irq,
                   0, dev_name(&pdev->dev), i2c);
    
    //时钟初始化

ret = i2c_add_adapter(&i2c->adap);//注册adapter对象
        |
        |
        i2c_register_adapter(adapter);
            |
            dev_set_name(&adap->dev, "i2c-%d", adap->nr); // /dev/i2d-0,1,2,
            adap->dev.bus = &i2c_bus_type; //adapter注册 到 i2c_bus_type
            adap->dev.type = &i2c_adapter_type;
            res = device_register(&adap->dev);
            of_i2c_register_devices(adap);
                |
                |
                for_each_available_child_of_node(adap->dev.of_node, node) {//遍历i2c4下的子节点
                    if (of_node_test_and_set_flag(node, OF_POPULATED))
                        continue;
                    of_i2c_register_device(adap, node);
                        |
                        |
                        struct i2c_board_info info = {};
                        addr_be = of_get_property(node, "reg", &len); //读i2c4下的子节点的reg属性
                        addr = be32_to_cpup(addr_be);
                        info.addr = addr;
                        result = i2c_new_device(adap, &info);
                            |
                            |
                            struct i2c_client    *client;
                            client = kzalloc(sizeof *client, GFP_KERNEL);//创建client对象
                            client->adapter = adap;//绑定adapter
                            client->addr = info->addr;//设置client的器件地址
                            client->dev.bus = &i2c_bus_type;//client注册到i2c总线
                }

2.2从设备驱动层    
#define i2c_add_driver(driver) \
    i2c_register_driver(THIS_MODULE, driver)
        |
        driver->driver.owner = owner;
        driver->driver.bus = &i2c_bus_type; //i2c_driver注册 到 i2c_bus_type

触摸屏I2C驱动移植相关推荐

  1. linux i2c 内核初始io,linux I2C驱动移植

    linux I2C驱动移植 I²C总线仅使用SCL,SDA两根信号线实现设备间的数据交互,被广泛应用于微控制领域芯片与芯片之间的通信,如EEPROM,实时时钟,小型LCD等与CPU之间的通信. I2C ...

  2. Zynq-Linux移植学习笔记之46-光模块I2C驱动移植

    1.背景介绍 近期板卡上开始使用中航光电的光模块,查阅资料发现这些光模块都可以通过I2C来获取状态信息并进行开关控制,描述如下,其中需要特别注意的是所有光模块的读写I2C地址都是一样的,不可以挂在一根 ...

  3. linux i2c触摸屏驱动程序,触摸屏i2c设备和驱动的创建流程及方法

    添加i2c设备的流程: 1. 初始化 i2c_board_info 结构信息 和 i2c_driver 结构 //设备驱动结构体 static struct i2c_driver goodix_ts_ ...

  4. NUC972触摸屏驱动移植过程分析(二)

    https://blog.csdn.net/b7376811/article/details/86607529 今天继续分析NUC972的触摸屏驱动移植过程,上一节主要分析了触摸屏需要数据,今天来分析 ...

  5. 2.6.36.2 s3c6410 触摸屏驱动移植。

    CSDN_Acanoe 的博客:http://blog.csdn.net/ACanoe 硬件环境:OK6410 A板,4.3 寸TFT 屏.  移植内核:Linux2.6.36.2 . 参考内核: 飞 ...

  6. 正点原子Linux阿尔法开发板4.3 寸多点电容触摸屏测试问题和gt9xx系列linux驱动移植

    正点原子Linux阿尔法开发板4.3 寸多点电容触摸屏测试问题和gt9xx系列linux驱动移植 正点原子官方CSDN 4.3 寸多点电容触摸屏测试问题 正点原子gt9xx系列linux驱动移植 1. ...

  7. 9.触摸屏驱动移植实战

    转自 https://edu.csdn.net/lecturer/505 朱老师物联网大讲堂 <5.linux驱动开发-第9部分-5.9.触摸屏驱动移植实战> 第一部分.章节目录 5.9. ...

  8. NUC972触摸屏驱动移植过程分析(一)

    https://blog.csdn.net/b7376811/article/details/86514683 因为下一个项目可能会用到触摸屏,所以这段时间对触摸屏的驱动的移植进行了研究,今天正好有机 ...

  9. 移植基于linux-2.6.26.5内核s3c2410触摸屏驱动移植

    移植基于linux-2.6.26.5内核s3c2410触摸屏驱动移植的过程记录下来: (1)首先打一个补丁:s3c2410_touchscreen.patch, 在内核解压的根目录下 patch -N ...

最新文章

  1. Nature子刊:精胺介导稻瘟病菌侵染水稻叶片的新机制!
  2. OVH公司进军英国数据中心市场
  3. GoldenGate SQL error 1403 mapping 错误解决方案
  4. OAuth2认证有一定的了解
  5. Scrapy_XPath选择器
  6. java解析tcp报文_JAVA语言TCP通信和JDBC示例(AIS信息解析)
  7. 启动车子温车_什么是冷车启动
  8. golang 对象转json
  9. window下安装ruby与sass(附ruby)
  10. 服务器维护封号,LOL客服的关于他们自己服务器问题导致账号被封号的问题
  11. 基于PHP+MySQL动漫周边商城销售网站的开发与设计
  12. 基于AT89S52单片机的蘑菇大棚环境监测系统论文(附录代码)
  13. windows渗透利器——PentestBox的内功和攻击力
  14. Android10.0 os定制化系列讲解导读
  15. 被风吹过的冬天 ——2
  16. 2017年12月英语六级翻译洞庭湖
  17. DVWA 之 CSP Bypass
  18. 以太坊黄皮书(1~6章)
  19. 被面试官问到频繁跳槽,求职者应该怎么回
  20. DDD(领域驱动设计)系列主题:DDD兴起的原因以及与微服务的关系

热门文章

  1. Makefile文件是什么?(一)
  2. Makefile文件是什么
  3. 判断当前浏览器是否为IE11
  4. Mac 设置 xdebug + Sublime 方法整理
  5. css动画其他div,删除另一个div时的CSS3 Transition动画
  6. 计算机网络socket翻译成中文,Socket的错误码和描述(中英文翻译)
  7. Oracle EBS 12.2.7系统克隆教程
  8. 克隆linux系统之后如何配置网络ip
  9. 未来微型计算机发展趋势,简述什么是单片机(单片机未来发展趋势)
  10. 数字图像处理知识点梳理——第八章 图像压缩