RK3568驱动指南|第十五篇 I2C-第173章 完善FT5X06设备节点和驱动

瑞芯微RK3568芯片是一款定位中高端的通用型SOC,采用22nm制程工艺,搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码,支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU,可用于轻量级人工智能应用。RK3568 支持安卓 11 和 linux 系统,主要面向物联网网关、NVR 存储、工控平板、工业检测、工控盒、卡拉 OK、云终端、车载中控等行业。


【公众号】迅为电子

【粉丝群】258811263(加群获取驱动文档+例程)

【视频观看】嵌入式学习之Linux驱动(第十五篇 I2C_全新升级)_基于RK3568

【购买链接】迅为RK3568开发板瑞芯微Linux安卓鸿蒙ARM核心板人工智能AI主板


第173章 完善FT5X06设备节点和驱动

在上一章中我们编写了I2C 的Platform device代码,这种方式后面已经被设备树所取代,这里讲解只是为了更好的理解I2C子系统框架,而从本章节开始将会回到FT5X06设备树和I2C驱动程序的完善,在本章将先对FT5X06输入子系统相关的部分进行完善。

173.1 完善FT5X06设备节点

本实验修改完成的设备树对应的网盘路径为:iTOP-RK3568开发板【底板V1.7版本】\03_【iTOP-RK3568开发板】指南教程\02_Linux驱动配套资料\04_Linux驱动程序\104_ft5x06_03\01_修改完成的设备树

在第170章中已经编写了FT5X06设备树框架,具体如下所示:

&i2c1 {
    status = "okay";

    myft5x06: my-ft5x06@38 {
        compatible = "my-ft5x06";
        reg = <0x38>;
    };
};

而FT5X06触摸芯片除了I2C部分,还有另外两个GPIO分别为中断引脚和复位引脚,每个引脚对应的功能匹配表格如下所示:

在开发板上电的时候,FT5X06芯片复位之后才能正常使用,而当屏幕按下之后,需要产生一个中断信号,在驱动中通过中断服务函数来读取触摸芯片的寄存器,从而上报一系列的数据,填充完成的设备树内容如下所示:

&i2c1 {
    status = "okay";

    myft5x06: my-ft5x06@38 {
        compatible = "my-ft5x06";
        reg = <0x38>;
        reset-gpios = <&gpio0 RK_PB6 GPIO_ACTIVE_LOW>;
        interrupt-parent = <&gpio3>;
        interrupts-gpio = <&gpio3 RK_PA5 GPIO_ACTIVE_LOW>;
        interrupts = <RK_PA5 IRQ_TYPE_LEVEL_LOW>;
        pinctrl-names = "default";
        pinctrl-0 = <&myft5x06_pins>;
    };
};

reset-gpios = <&gpio0 RK_PB6 GPIO_ACTIVE_LOW>;: 定义了设备的复位引脚,连接到 GPIO0 的 RK_PB6 引脚,电平为低电平有效。

interrupt-parent = <&gpio3>;: 指定中断的父节点为 GPIO3。

interrupts-gpio = <&gpio3 RK_PA5 GPIO_ACTIVE_LOW>;: 定义了设备的中断引脚,连接到 GPIO3 的 RK_PA5 引脚,电平为低电平触发。

interrupts = <RK_PA5 IRQ_TYPE_LEVEL_LOW>;: 进一步描述了中断的触发方式,为电平低电平触发。

pinctrl-names = "default"; pinctrl-0 = <&myft5x06_pins>;: 指定了设备使用的默认针脚配置。

这里指定的pinctrl节点名为myft5x06_pins,所以还需要对pinctrl节点进行追加,追加内容如下所示:

&pinctrl {
        myft5x06 {
                myft5x06_pins: myft5x06-pins {
                rockchip,pins =
                    <0 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>,
                    <0 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
                };  
        };  
};

保存退出之后,重新编译内核源码,得到boot.img镜像,然后烧写到开发板。

173.2 完善FT5X06驱动

本实验修改完成的驱动对应的网盘路径为:iTOP-RK3568开发板【底板V1.7版本】\03_【iTOP-RK3568开发板】指南教程\02_Linux驱动配套资料\04_Linux驱动程序\104_ft5x06_03\03_module

在171章已经编写了最简单的I2C驱动框架程序,而在上个小节填充了设备树的中断和复位引脚之后,同样需要完善FT5X06驱动对应的部分,申请两个GPIO,要求在加载驱动之后reset引脚进行复位,编写中断引脚的中断服务函数,当按下MIPI屏幕之后就会产生中断,并在中断服务函数中添加打印信息。

编写完成的驱动程序如下所示:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/delay.h>

// 定义 ft5x06 设备的 GPIO 描述符
struct gpio_desc *reset_gpio, *irq_gpio;

// ft5x06 中断处理函数
irqreturn_t ft5x06_handler(int irq, void *args)
{
    printk("This is ft5x06 handler\n");
    // 返回中断已处理标志
    return IRQ_RETVAL(IRQ_HANDLED);
}

// ft5x06 设备的探测函数
int ft5x06_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
    int ret;
    printk("This is ft5x06 probe\n");

    // 获取 reset GPIO 描述符
    reset_gpio = gpiod_get_optional(&client->dev, "reset", 0);
    if (!reset_gpio) {
        printk("gpiod_get_optional reset gpio is error\n");
        return -1;
    }

    // 获取 irq GPIO 描述符
    irq_gpio = gpiod_get_optional(&client->dev, "interrupts", 0);
    if (!irq_gpio) {
        printk("gpiod_get_optional irq gpio is error\n");
        return -1;
    }

    // 设置 reset GPIO 为输出,并拉低 5ms 后拉高
    gpiod_direction_output(reset_gpio, 0);
    msleep(5);
    gpiod_direction_output(reset_gpio, 1);

    // 请求中断,设置为下降沿触发,单次触发
    ret = request_irq(client->irq, ft5x06_handler,
                     IRQ_TYPE_EDGE_FALLING | IRQF_ONESHOT, "ft5x06 irq", NULL);
    if (ret < 0) {
        printk("request irq is error\n");
        return -2;
    }

    return 0;
}
// ft5x06 设备的移除函数
int ft5x06_remove(struct i2c_client *client)
{
    free_irq(client->irq, NULL);
    gpiod_put(reset_gpio);
    gpiod_put(irq_gpio);
    return 0;
}

// 定义 i2c_device_id 结构体数组,用于标识 ft5x06 设备
static const struct i2c_device_id ft5x06_id[] = {
    { "my-ft5x06", 0 },
    { }
};

// 定义 i2c_driver 结构体,描述 ft5x06 设备驱动
static struct i2c_driver ft5x06_driver = {
    .driver = {
        .name = "my-ft5x06",
        .owner = THIS_MODULE,
    },
    .probe = ft5x06_probe,
    .remove = ft5x06_remove,
    .id_table = ft5x06_id,
};

// 驱动初始化函数
static int __init ft5x06_driver_init(void)
{
    int ret;
    // 注册 I2C 设备驱动
    ret = i2c_add_driver(&ft5x06_driver);
    if (ret < 0) {
        printk("i2c_add_driver is error\n");
        return ret;
    }
    return 0;
}

// 驱动退出函数
static void __exit ft5x06_driver_exit(void)
{
    // 注销 I2C 设备驱动
    i2c_del_driver(&ft5x06_driver);
}

module_init(ft5x06_driver_init);
module_exit(ft5x06_driver_exit);
MODULE_LICENSE("GPL");

173.3 运行测试

173.3.1 编译驱动程序

首先在上一小节中的ft5x06_driver.c代码同一目录下创建 Makefile 文件,Makefile 文件内容如下所示:

export ARCH=arm64#设置平台架构
export CROSS_COMPILE=aarch64-linux-gnu-#交叉编译器前缀
obj-m += ft5x06_driver.o    #此处要和你的驱动源文件同名
KDIR :=/home/topeet/Linux/linux_sdk/kernel    #这里是你的内核目录                                                                                                                            
PWD ?= $(shell pwd)
all:
    make -C $(KDIR) M=$(PWD) modules    #make操作
clean:
    make -C $(KDIR) M=$(PWD) clean    #make clean操作

对于Makefile的内容注释已在上图添加,保存退出之后,来到存放platform_driver.c和Makefile文件目录下,如下图所示:

然后使用命令“make”进行驱动的编译,编译完成如下图所示:

编译完生成ft5x06_driver.ko目标文件,如下图所示:

173.3.2 运行测试

在进行实验之前,首先要确保开发板烧写的是我们在173.1小节中编译出来的boot.img。开发板启动之后进入系统之后如下图所示:

然后将上一个小节编译完成的ko文件拷贝到开发板上,拷贝完成如下图所示:

然后使用以下命令加载驱动,加载完成如下图所示:

insmod ft5x06_driver.ko

然后点击MIPI屏幕,可以看到中断服务函数中的打印信息“This is ft5x06 handler”具体如下所示:

然后使用以下命令进行驱动模块的卸载,如下图所示:

rmmod ft5x06_driver.ko

由于没有在remove卸载函数中添加打印相关内容,所以使用rmmod命令卸载驱动之后,没有任何打印,至此,初步完善 I2C驱动实验就完成了。

  • 21
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值