RK3568-I2C操作

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驱动框架由以下几个主要部分组成:

  1. I2C总线控制器驱动: I2C总线控制器驱动是用于支持硬件I2C总线控制器的内核模块。每种硬件架构通常都有特定的I2C总线控制器驱动。这些驱动程序负责配置和管理硬件I2C总线控制器,并提供了一组标准的操作接口供上层驱动程序和应用程序使用。

  2. I2C设备驱动: I2C设备驱动程序是用于支持特定类型的I2C设备的内核模块。每个I2C设备都有一个相应的驱动程序,该驱动程序知道如何与该设备通信并提供了设备特定的操作接口。I2C设备驱动程序通常与I2C总线控制器驱动程序配对使用。

  3. I2C适配层: I2C驱动框架还包括一个I2C适配层,它提供了一个统一的API,使I2C设备驱动程序能够与不同的I2C总线控制器驱动程序进行通信。这使得I2C设备驱动程序能够在不同的硬件平台上无需修改即可重用。

  4. 用户空间接口: Linux内核提供了一组用户空间接口,允许应用程序通过文件系统访问I2C设备。通常,这些接口位于/dev/i2c-X,其中X是I2C适配层上的I2C总线号。应用程序可以打开这些文件,然后使用ioctl等系统调用来与I2C设备进行通信。

I2C驱动框架的工作流程如下:

  1. I2C设备驱动程序注册到I2C驱动框架中,指定其支持的I2C设备地址。

  2. 当内核初始化时,它会扫描系统上的I2C总线,检测连接的I2C设备,并将这些设备与相应的驱动程序匹配。

  3. 当应用程序需要与I2C设备通信时,它可以打开适当的设备文件(如/dev/i2c-X),并使用文件操作接口与I2C设备进行交互。

  4. I2C适配层将应用程序的请求传递给相应的I2C控制器驱动程序。

使用方式

  1. 配置好设备树

驱动代码在/kernel/drivers/i2c/busses/i2c-rk3x.c,i2c-rk3x.c 驱动的配置都在 DTS,参考文件Documentation/devicetree/bindings/i2c/i2c-rk3x.txt。重点说明其中配置项,i2c-scl-rising-time-nsi2c-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>; 
	};
};
  1. 操作设备节点

支持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;
}

2. 使用I2Ctools

参考:https://blog.csdn.net/anyuliuxing/article/details/106382827

i2c-tools 是一组用于在Linux系统中进行I2C(Inter-Integrated Circuit)总线设备操作和调试的命令行工具。这些工具允许用户与I2C设备进行通信、扫描I2C总线、读写I2C寄存器以及进行其他I2C相关的操作。以下是 i2c-tools 的一些常见工具和其功能:

  1. i2cdetect: i2cdetect 命令用于扫描I2C总线,检测连接到总线上的I2C设备以及它们的I2C地址。它会生成一个简单的表格,显示哪些地址被使用,哪些没有。

  2. i2cget: i2cget 命令用于从指定I2C设备的寄存器中读取数据。用户可以指定I2C设备的地址、寄存器地址和读取的数据格式。

  3. i2cset: i2cset 命令用于向指定I2C设备的寄存器中写入数据。用户可以指定I2C设备的地址、寄存器地址和要写入的数据。

  4. i2cdump: i2cdump 命令用于以十六进制格式显示指定I2C设备的寄存器内容。它可用于查看I2C设备的寄存器值,以进行调试和分析。

  5. i2ctransfer: i2ctransfer 命令用于执行更复杂的I2C传输操作,包括读取和写入多个寄存器、使用不同的I2C协议等。

  6. i2csettool: i2csettool 命令用于配置I2C设备的特定寄存器,以更改设备的行为或属性。

这些工具通常用于调试和配置与I2C总线连接的各种设备,如传感器、显示屏、EEPROM等。它们为开发人员和系统管理员提供了在终端上进行I2C通信和调试的便捷方式。

要使用这些工具,首先需要安装 i2c-tools 软件包(如果尚未安装),然后可以在终端中直接运行相应的命令,按照需要进行I2C通信和调试。

3. 自己写个驱动

参考:https://blog.csdn.net/lhl_blog/article/details/107770965

你可能感兴趣的:(#,Linux,rk3568,i2c)