RK3568内有6个I2C控制器,对应/dev
下的i2c-0 i2c-1 i2c-3 i2c-5 i2c-6 i2c-7
,控制器支持下列功能︰
参考:
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
:
&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
#include
#include
#include
#include
#include
#include
#include
#include
/* 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;
}
参考:https://blog.csdn.net/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通信和调试。
参考:https://blog.csdn.net/lhl_blog/article/details/107770965