RK3568-I2C操作
RK3568内有6个I2C控制器,对应/dev下的i2c-0 i2c-1 i2c-3 i2c-5 i2c-6 i2c-7 ,控制器支持下列功能︰
- 兼容 I2C 与 SMBus 总线
- 仅支持主模式下的 I2C 总线
- 软件可编程时钟频率支持到 400kbps,部分芯片可高达 1000kbps
- 支持 7 位和 10 位寻址模式
- 一次中断或轮询至多 32 个字节的数据传输
1. 使用自带的I2C控制器驱动
参考:
https://juejin.cn/post/7001850979356262437
https://zhuanlan.zhihu.com/p/443741898
实现原理
Linux中I2C驱动框架由以下几个主要部分组成:
-
I2C总线控制器驱动: I2C总线控制器驱动是用于支持硬件I2C总线控制器的内核模块。每种硬件架构通常都有特定的I2C总线控制器驱动。这些驱动程序负责配置和管理硬件I2C总线控制器,并提供了一组标准的操作接口供上层驱动程序和应用程序使用。
-
I2C设备驱动: I2C设备驱动程序是用于支持特定类型的I2C设备的内核模块。每个I2C设备都有一个相应的驱动程序,该驱动程序知道如何与该设备通信并提供了设备特定的操作接口。I2C设备驱动程序通常与I2C总线控制器驱动程序配对使用。
-
I2C适配层: I2C驱动框架还包括一个I2C适配层,它提供了一个统一的API,使I2C设备驱动程序能够与不同的I2C总线控制器驱动程序进行通信。这使得I2C设备驱动程序能够在不同的硬件平台上无需修改即可重用。
-
用户空间接口: Linux内核提供了一组用户空间接口,允许应用程序通过文件系统访问I2C设备。通常,这些接口位于/dev/i2c-X,其中X是I2C适配层上的I2C总线号。应用程序可以打开这些文件,然后使用ioctl等系统调用来与I2C设备进行通信。
I2C驱动框架的工作流程如下:
-
I2C设备驱动程序注册到I2C驱动框架中,指定其支持的I2C设备地址。
-
当内核初始化时,它会扫描系统上的I2C总线,检测连接的I2C设备,并将这些设备与相应的驱动程序匹配。
-
当应用程序需要与I2C设备通信时,它可以打开适当的设备文件(如/dev/i2c-X),并使用文件操作接口与I2C设备进行交互。
-
I2C适配层将应用程序的请求传递给相应的I2C控制器驱动程序。
使用方式
- 配置好设备树
驱动代码在/kernel/drivers/i2c/busses/i2c-rk3x.c,i2c-rk3x.c 驱动的配置都在 DTS,参考文件Documentation/devicetree/bindings/i2c/i2c-rk3x.txt。重点说明其中配置项,i2c-scl-rising-time-ns,i2c-scl-falling-time-ns:
- clock-frequency: 默认 frequency 为 100k 可不配置,其它 I2C 频率需要配置,最大可配置频率由i2c-scl-rising-time-ns 决定;例如配置 400k,clock-frequency=<400000>。
- i2c-scl-rising-time-ns:SCL 上升沿时间由硬件决定,改变上拉电阻可调节该时间,需通过示波器量测,参考上图;例如测得 SCL 上升沿 365ns,- i2c-scl-rising-time-ns=<365>。(默认可以不配置,但必须保证当前的上升沿时间不能超过所配置频率下的 I2C 标准所定义的最大上升沿时间)
- i2c-scl-falling-time-ns: SCL 下降沿时间, 一般不变, 等同于 i2c-sda-falling-time-ns。(默认也可以不配置)
&i2c1 {
status = "okay";
i2c-scl-rising-time-ns = <265>;
i2c-scl-falling-time-ns = <11>;
clock-frequency = <400000>;
es8316: es8316@10 {
#sound-dai-cells = <0>;
compatible = "everest,es8316";
reg = <0x10>;
clocks = <&cru SCLK_I2S_8CH_OUT>;
clock-names = "mclk";
spk-con-gpio = <&gpio0 11 GPIO_ACTIVE_HIGH>;
hp-det-gpio = <&gpio4 28 GPIO_ACTIVE_LOW>;
};
};
- 操作设备节点
支持open、close、write、read、ioctl操作。
注意,这里的read和write只能接收/发送一个字节数据。如果要发送复合数据,即一次读写多字节数据,要使用ioctl接口。如果要使用SMbus协议,也必须使用ioctl接口。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/i2c-dev.h>
/* i2c_test r addr
* i2c_test w addr val
*/
void print_usage(char *file)
{
printf("%s r addr\n", file);
printf("%s w addr val\n", file);
}
int main(int argc, char **argv)
{
int fd;
unsigned char buf[2];
if ((argc != 3) && (argc != 4))
{
print_usage(argv[0]);
return -1;
}
// 打开设备节点
fd = open("/dev/i2c-0", O_RDWR);
if (fd < 0)
{
printf("can't open /dev/i2c-0\n");
return -1;
}
ioctl(fd,I2C_SLAVE,0x50); // 设置从设备地址
ioctl(fd,I2C_TIMEOUT,1); // 设置超时
ioctl(fd,I2C_RETRIES,1); // 设置重试次数
if (strcmp(argv[1], "r") == 0)
{
buf[0] = strtoul(argv[2], NULL, 0);
write(fd, buf, 1); // 先写入要读取的设备内部地址
read(fd, buf, 1); // 再读取一个字节
printf("data: %c, %d, 0x%2x\n", buf[0], buf[0], buf[0]);
}
else if (strcmp(argv[1], "w") == 0)
{
buf[0] = strtoul(argv[2], NULL, 0);
buf[1] = strtoul(argv[3], NULL, 0);
write(fd, buf, 2);
}
else
{
print_usage(argv[0]);
return -1;
}
return 0;
}
2. 使用I2Ctools
参考:https://blog.youkuaiyun.com/anyuliuxing/article/details/106382827
i2c-tools 是一组用于在Linux系统中进行I2C(Inter-Integrated Circuit)总线设备操作和调试的命令行工具。这些工具允许用户与I2C设备进行通信、扫描I2C总线、读写I2C寄存器以及进行其他I2C相关的操作。以下是 i2c-tools 的一些常见工具和其功能:
-
i2cdetect:
i2cdetect命令用于扫描I2C总线,检测连接到总线上的I2C设备以及它们的I2C地址。它会生成一个简单的表格,显示哪些地址被使用,哪些没有。 -
i2cget:
i2cget命令用于从指定I2C设备的寄存器中读取数据。用户可以指定I2C设备的地址、寄存器地址和读取的数据格式。 -
i2cset:
i2cset命令用于向指定I2C设备的寄存器中写入数据。用户可以指定I2C设备的地址、寄存器地址和要写入的数据。 -
i2cdump:
i2cdump命令用于以十六进制格式显示指定I2C设备的寄存器内容。它可用于查看I2C设备的寄存器值,以进行调试和分析。 -
i2ctransfer:
i2ctransfer命令用于执行更复杂的I2C传输操作,包括读取和写入多个寄存器、使用不同的I2C协议等。 -
i2csettool:
i2csettool命令用于配置I2C设备的特定寄存器,以更改设备的行为或属性。
这些工具通常用于调试和配置与I2C总线连接的各种设备,如传感器、显示屏、EEPROM等。它们为开发人员和系统管理员提供了在终端上进行I2C通信和调试的便捷方式。
要使用这些工具,首先需要安装 i2c-tools 软件包(如果尚未安装),然后可以在终端中直接运行相应的命令,按照需要进行I2C通信和调试。
3. 自己写个驱动
参考:https://blog.youkuaiyun.com/lhl_blog/article/details/107770965
357

被折叠的 条评论
为什么被折叠?



