RK3568驱动指南|第十五篇 I2C-第182章 使用Linux中默认的模拟I2C驱动程序

瑞芯微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主板


第182章 使用Linux中默认的模拟I2C驱动程序

在上一章中,从0编写了一个FT5X06触摸芯片的软件I2C驱动,而在实际使用中,并不需要完全从0开始编写软件I2C驱动,Linux内核中已经提供了软件I2C的驱动,在本章节中将会对Linux内核中的软件I2C驱动的使用进行讲解。

182.1 修改默认配置文件

默认情况下内核中并没有使能软件I2C,所以需要修改默认配置文件,勾选对应的配置,首先进入内核源码路径,使用以下命令进入menuconfig界面:

export ARCH=arm64

make rockchip_linux_defconfig

make menuconfig

进入menuconfig界面之后如下图所示: 

然后根据路径勾选软件I2C的配置选项,勾选完成如下图所示:

 > Device Drivers

> I2C support

> I2C Hardware Bus support

<*> GPIO-based bitbanging I2C

保存退出之后使用以下命令覆盖默认配置文件,覆盖完成如下图所示:

cp .config arch/arm64/configs/rockchip_linux_defconfig

 

至此,关于内核相关的配置就完成了。

182.2 完善设备树

i2c6:i2c6@gpio {compatible = "i2c-gpio";#address-cells = <1>;         #size-cells = <0>;             gpios = <&gpi00 RK PB4 GPIO ACTIVE_HIGH>;<&gpi00 RK PB3 GPIO ACTIVE_HIGH>;i2c-gpio,delay-us = <5>;    status = "disabled";        
};

内核配置修改完成之后,接下来完善该驱动对应的设备树,首先回到linux sdk根目录下,如下图所示:

然后使用以下命令对rk3568.dtsi进行修改,添加软件I2C的设备节点I2C6,添加内容如下所示:

vim kernel/arch/arm64/boot/dts/rockchip/rk3568.dtsi

 第2行的compatible属性指定了与驱动程序匹配的字符串,最终会匹配模拟GPIO驱动程序。

第5行和第6行定义了用于模拟I2C总线的两个GPIO,并设置为了高电平。

第7行的i2c-gpio,delay-us属性定义了在两个GPIO操作之间的延迟时间,以微秒为单位。这里设置为<5>表示5微秒的延迟。这在模拟I²C时序时是必需的,以确保时序符合I²C标准。

添加完成之后如下图所示:

然后使用以下命令对topeet_rk3568_lcds.dtsi进行修改,对I2C6节点进行追加,最佳FT5X06触摸芯片相关的内容,添加内容如下所示:

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

需要注意的是,由于之前编写的设备树节点名也叫myft5x06,会产生命名冲突,所以需要将之前编写的myft5x06设备树节点注释掉。修改添加完成如下图所示:

保存退出之后编译内核源码,得到boot.img镜像烧写到开发板上,为了方便,迅为已经将编译好的boot.img内核镜像放到了“iTOP-3568开发板\03_【iTOP-RK3568开发板】指南教程\02_Linux驱动配套资料\04_Linux驱动程序\112_soft_i2c_02\01_内核镜像”目录下,如下图所示:

182.3编写驱动程序

本小节使用的驱动程序模板为174.2小节完善I2C通信内容的代码,在该代码的基础上去掉了GPIO相关的内容,修改完成的驱动程序路径为“【iTOP-RK3568开发板】指南教程\02_Linux驱动配套资料\04_Linux驱动程序\112_soft_i2c_02\02_module”,具体内容如下所示:

#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 设备的 i2c 客户端对象指针
struct i2c_client *ft5x06_client;// 读取 ft5x06 设备寄存器的函数
int ft5x06_read_reg(u8 reg_addr)
{u8 data;// 定义两个 i2c_msg 结构体,分别表示写操作和读操作struct i2c_msg msgs[2] = {[0] = {.addr = ft5x06_client->addr, // 设备地址.flags = 0,        // 写操作.len = sizeof(reg_addr),.buf = &reg_addr,  // 写入要读取的寄存器地址},[1] = {.addr = ft5x06_client->addr,.flags = I2C_M_RD, // 读操作.len = sizeof(data),.buf = &data,      // 读取到的数据存储位置},};// 使用 i2c_transfer 函数进行 i2c 总线读取操作// 如果读取失败,返回 -EIO 错误码if (i2c_transfer(ft5x06_client->adapter, msgs, ARRAY_SIZE(msgs)) != ARRAY_SIZE(msgs)){return -EIO;}return data; // 返回读取到的寄存器值
}// 向 ft5x06 设备写入寄存器的函数
void ft5x06_write_reg(u8 reg_addr, u8 *data, u16 len)
{u8 buff[256];struct i2c_msg msgs[] = {[0] = {.addr = ft5x06_client->addr, // 设备地址.flags = 0,        // 写操作.len = len + 1,    // 数据长度 + 寄存器地址长度.buf = buff,       // 数据缓冲区},};buff[0] = reg_addr;       // 写入寄存器地址memcpy(&buff[1], data, len); // 写入数据// 使用 i2c_transfer 函数进行 i2c 总线写入操作// 如果写入失败,直接返回if (i2c_transfer(ft5x06_client->adapter, msgs, ARRAY_SIZE(msgs)) != ARRAY_SIZE(msgs)) {return;}
}// ft5x06 设备的探测函数
int ft5x06_probe(struct i2c_client *client, const struct i2c_device_id *id)
{int value;printk("This is ft5x06 probe\n");ft5x06_client = client; // 保存 i2c 客户端对象指针// 写寄存器ft5x06_write_reg(0x80, &(u8){0x4b}, 1);// 读寄存器value = ft5x06_read_reg(0x80);printk("reg 0x80 is %x\n", value);return 0;
}// ft5x06 设备的移除函数
// 参数 client 是 i2c 客户端对象指针
int ft5x06_remove(struct i2c_client *client)
{// 释放中断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");

182.4运行测试

182.4.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目标文件,如下图所示:

182.4.2 运行测试

首先确保烧写的是182.2小节编译出来的内核镜像,然后启动开发板,开发板启动进入系统之后如下图所示:

然后查看I2C设备节点,如果存在i2c-6节点就证明内核配置正确,如下图所示:

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

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

insmod ft5x06_driver.ko

 可以看到写入到0x80地址的0x4b数据就被成功读取了出来,证明I2C通信成功了,至此,使用内核默认的软件I2C驱动实验就测试完成。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/865213.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

线性代数笔记

行列式 求高阶行列式 可以划上三角 上三角 余子式 范德蒙行列式 拉普拉斯公式 行列式行列对换值不变 矩阵 矩阵的运算 同型矩阵加减 对应位置相加减 矩阵的乘法 左边第 i 行 一次 相乘求和 右边 第 j 列 eg 中间相等 两边规模 矩阵的幂运算 解题思路 找规律 数学归纳…

CVE-2024-6387 分析

文章目录 1. 漏洞成因2. 漏洞利用前置知识2.1 相关 SSH 协议报文格式2.2 Glibc 内存分配相关规则 3. POC3.1 堆内存布局3.2 服务端解析数据时间测量3.3 条件竞争3.4 FSOP 4. 相关挑战 原文链接&#xff1a;个人博客 近几天&#xff0c;OpenSSH爆出了一个非常严重的安全漏洞&am…

重生奇迹mu精灵之心怎么搭配

玩家可以通过召唤来召唤多种精灵之心&#xff0c;每种精灵之心增加的属性也不同。精灵之心的作用是为了提升各种各样的属性。我们可以通过召唤获得精灵之心&#xff0c;前面的解锁费用较低&#xff0c;而后面的解锁需要大量的金币来解锁。 召唤精灵之心后&#xff0c;我们可以…

数据结构(JAVA)—代码题

01-数据结构—判断题 02-数据结构—选择题 03 数据结构—多选填空程序填空 ​ 01-顺序表的建立及遍历 import java.util.Iterator; import java.util.LinkedList; import java.util.ListIterator; import java.util.Scanner;public class Main {public static void main(St…

Hadoop-09-HDFS集群 JavaClient 代码上手实战!详细附代码 安装依赖 上传下载文件 扫描列表 PUT GET 进度条显示

章节内容 上一节完成&#xff1a; HDFS的集群启动HDFS的命令行操作HDFS 上传下载移动重命名等操作 背景介绍 这里是三台公网云服务器&#xff0c;每台 2C4G&#xff0c;搭建一个Hadoop的学习环境&#xff0c;供我学习。 之前已经在 VM 虚拟机上搭建过一次&#xff0c;但是没…

基于FPGA的DDS信号发生器

前言 此处仅为基于Vivado实现DDS信号发生器的仿真实现&#xff0c;Vivado的安装请看下面的文章&#xff0c;这里我只是安装了一个标准版本&#xff0c;只要能够仿真波形即可。 FPGA开发Vivado安装教程_vivado安装 csdn-CSDN博客 DDS原理 DDS技术是一种通过数字计算生成波形…

Pandas_DataFrame读写详解:案例解析(第24天)

系列文章目录 一、 读写文件数据 二、df查询数据操作 三、df增加列操作 四、df删除行列操作 五、df数据去重操作 六、df数据修改操作 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 系列文章目录前言一、 读写文…

Web 基础与 HTTP 协议

Web 基础与 HTTP 协议 一、Web 基础1.1域名和 DNS域名的概念Hosts 文件DNS&#xff08;Domain Name System 域名系统&#xff09;域名注册 1.2网页与 HTML网页概述HTML 概述网站和主页Web1.0 与 Web2.0 1.3静态网页与动态网页静态网页动态网页 二、HTTP 协议1.1HTTP 协议概述1.…

秋招——MySQL补充——MySQL是如何加行级锁

文章目录 引言正文什么SQL语句会加行级锁查询操作增加对应的行级锁事务的写法 update和delete修改操作也会增加行级锁 行级锁有哪些种类记录锁间隙锁Next-Key锁 MySQL是如何加行级锁&#xff1f;唯一索引等值查询查询记录是存在的查询记录是不存在的 唯一索引范围查找针对大于或…

《梦醒蝶飞:释放Excel函数与公式的力量》8.4 COUNTIF函数

8.4 COUNTIF函数 COUNTIF函数是Excel中常用的统计函数之一&#xff0c;用于统计指定条件下的单元格数量。通过COUNTIF函数&#xff0c;我们可以轻松地对数据进行条件筛选和统计分析。下面将从函数简介、语法、基本用法、注意事项、高级应用、实战练习和小节几个方面展开介绍。…

爬虫笔记19——代理IP的使用

访问网站时IP被阻止 有些网站会设置特定规则来限制用户的访问&#xff0c;例如频率限制、单一账户多次登录等。 网站为了保护自身安全和用户体验&#xff0c;会设置防御机制&#xff0c;将涉嫌恶意行为的IP地址加入黑名单并屏蔽访问。如果用户在使用网站时违反了这些规则&…

格式化选NTFS还是exFAT 格式化NTFS后Mac不能用怎么办 移动硬盘格式化ntfs和exfat的区别

面对硬盘、U盘或移动硬盘的格式化决策&#xff0c;NTFS与exFAT作为主流的文件系统&#xff0c;用户在选择时可以根据它们的不同特点来选择适用场景。下面我们来看看格式化选NTFS还是exFAT&#xff0c;格式化NTFS后Mac不能用怎么办的相关内容。 一、格式化选NTFS还是exFAT 在数…

十四、【源码】@Autowired、@Value、@Component

源码地址&#xff1a;https://github.com/spring-projects/spring-framework 仓库地址&#xff1a;https://gitcode.net/qq_42665745/spring/-/tree/14-auto-property Autowired、Value、Component 注解注入属性的实现分散在refresh容器的各个方法中&#xff0c;梳理&#x…

docker 搭建 AI大数据模型 --- 使用GPU

docker 搭建 AI大数据模型 — 使用GPU方式 搭建本地大模型&#xff0c;最简单的方法&#xff01;效果直逼GPT 服务器GPU系统HP580 G8P40Rocky9.2 安装程序AnythingLLM前端界面Open WebUIChatOllamaollama 一、AnythingLLM 介绍 AnythingLLM 是 Mintplex Labs Inc. 开发的一…

9.(vue3.x+vite)修改el-input,el-data-picker样式

效果预览 二:相关代码 <template><div style="padding: 50px"><el-input placeholder="请输入模型名称" style="width: 260px" /><br /

Java灵活用工2.0报价单微信小程序+APP+微信公众号 源码

&#x1f680;【开篇&#xff1a;解锁灵活用工的高效时代】 在人力资源市场日益灵活的今天&#xff0c;如何快速、准确地生成报价单&#xff0c;成为企业吸引并管理自由职业者的关键。而“灵活用工报价单微信小程序APP微信公众号源码”正是这样一款集高效、便捷于一体的解决方…

YOLO在目标检测与视频轨迹追踪中的应用

YOLO在目标检测与视频轨迹追踪中的应用 引言 在计算机视觉领域&#xff0c;目标检测与视频轨迹追踪是两个至关重要的研究方向。随着深度学习技术的飞速发展&#xff0c;尤其是卷积神经网络&#xff08;CNN&#xff09;的广泛应用&#xff0c;目标检测与视频轨迹追踪的性能得到…

YOLO-V2

一、V2版本细节升级 1、YOLO-V2&#xff1a; 更快&#xff01;更强 1.1 做的改进内容 1. YOLO-V2-Batch Normalization V2版本舍弃Dropout&#xff0c;卷积后每一层全部加入Batch Normalization网络的每一层的输入都做了归一化&#xff0c;收敛相对更容易经过Batch Norma…

【C++】相机标定源码笔记- RGB 相机与 ToF 深度传感器校准类

类的设计目标是为了实现 RGB 相机与 ToF 深度传感器之间的高精度校准&#xff0c;从而使两种类型的数据能够在同一个坐标框架内被整合使用。这在很多场景下都是非常有用的&#xff0c;比如在3D重建、增强现实、机器人导航等应用中&#xff0c;能够提供更丰富的场景信息。 -----…