首页 > 其他分享 >I2C相关结构体讲解:i2c_adapter、i2c_algorithm、i2c_msg

I2C相关结构体讲解:i2c_adapter、i2c_algorithm、i2c_msg

时间:2024-10-15 19:20:07浏览次数:3  
标签:i2c struct algorithm adapter I2C Data 设备

往期内容

I2C子系统专栏:

  1. I2C(IIC)协议讲解
  2. SMBus 协议详解

总线和设备树专栏:

  1. 专栏地址
  2. 导航篇 – 专栏未篇

1.框图

画板

建议右击图片在新标签页打开预览

i2c_transfer函数就是读取i2c设备的信息或者输出信息给i2c设备的函数

比如发送app发送数据给i2c设备,i2c设备的驱动程序会调用到i2c_transfer函数,将信息发送给i2c控制器,I2C控制器就能根据协议调用内部i2c_adapter定义的传输函数(比如master_xfer和smbus_xfer)向设备发送数据

又比如想要读取i2c设备的数据,通过i2c_transfer来读取,会告诉i2c控制器调用相关的读函数来读取到i2c设备的数据(比如读取到Buf中,将buf传送回app)

结构体刚开始的话,看到这其实已经差不多了,当然,有兴趣深究的可以继续往下看:

2. struct i2c_adapter

代表着一个I2C 控制器,同时也标识着物理的I2C总线,并且有着一套访问I2C设备的算法,其实也就是协议类型:I2C/SMbus协议等

\Linux-4.9.88\include\linux\i2c.h:
/*
 * i2c_adapter is the structure used to identify a physical i2c bus along
 * with the access algorithms necessary to access it.
 */
struct i2c_adapter {
	struct module *owner;
	unsigned int class;		  /* classes to allow probing for */
	const struct i2c_algorithm *algo; /* the algorithm to access the bus */
	void *algo_data;

	/* data fields that are valid for all devices	*/
	const struct i2c_lock_operations *lock_ops;
	struct rt_mutex bus_lock;
	struct rt_mutex mux_lock;

	int timeout;			/* in jiffies */
	int retries;
	struct device dev;		/* the adapter device */

	int nr;
	char name[48];  // 表示 I2C 适配器的名字
	struct completion dev_released;  //用于同步释放控制器资源的完成机制

	struct mutex userspace_clients_lock; //用于保护用户空间 I2C 客户端的并发访问
	struct list_head userspace_clients;  //维护一个用户空间 I2C 客户端的链表。通过这个链表,适配器可以跟踪注册到它的用户空间客户端

	struct i2c_bus_recovery_info *bus_recovery_info;//当 I2C 总线发生错误或死锁时,可以尝试通过 bus_recovery_info 中定义的方法进行总线恢复,例如通过 GPIO 拉低总线或者其他恢复手段
	const struct i2c_adapter_quirks *quirks;//定义适配器的某些特殊行为或限制
};

struct module *owner: 用于指向当前拥有这个 I2C 控制器的模块。这个成员确保了模块在其设备未完全释放时不会被卸载。典型情况下会使用 THIS_MODULE 来指向当前模块。

unsigned int class: 用于表示该 I2C 适配器支持的设备类型(类)。 class 字段用于限制能够自动挂载到这个适配器上的设备类型 :

  • I2C_CLASS_HWMON:支持硬件监控设备。
  • I2C_CLASS_DDC:用于显示设备的 DDC 通道。
  • I2C_CLASS_SPD:支持 SPD 存储设备。
  • I2C_CLASS_DEPRECATED:表示不再支持的设备类型。

const struct i2c_algorithm *algo**:**下一点中再细讲

void *algo_data 用于存储算法(algo)相关的私有数据。 允许驱动在适配器与其使用的算法之间共享特定于适配器的上下文数据。

const struct i2c_lock_operations *lock_ops 如果某些适配器需要特殊的锁定行为,可以在这里定义自定义的锁操作,以确保在并发访问总线时保持正确的同步。

struct rt_mutex bus_lock 多设备可能同时尝试访问 I2C 总线,这里用 rt_mutex 互斥锁来保护总线,确保不会发生并发访问问题。

struct rt_mutex mux_lockbus_lock 类似,保护 I2C 总线多路复用器(mux)的同步访问。 在某些情况下,一个 I2C 控制器可能连接多个 I2C 总线,通过一个多路复用器进行选择,mux_lock 保护对该复用器的访问。

int timeoutint retries 定义 I2C 传输的超时时间,单位是 jiffies; 定义 I2C 传输失败后的重试次数。

struct device dev:I2C framework将I2C adapter当做了I2C bus中的一类特殊的设备,因此dev变量是它在设备模型中的体现。

int nr 控制器的编号(ID),在 /sys/bus/i2c/devices/i2c-n 中表示该总线。

剩下的就直接注释在代码中了。

3. struct i2c_algorithm

用于定义一个 I2C 控制器器(i2c_adapter)的传输方法(I2C 或 SMBus)。它主要用于描述控制器器的操作方式,并为设备驱动提供传输功能接口

\Linux-4.9.88\include\uapi\linux\i2c.h
/**
 * struct i2c_algorithm - represent I2C transfer method
 * @master_xfer: Issue a set of i2c transactions to the given I2C adapter
 *   defined by the msgs array, with num messages available to transfer via
 *   the adapter specified by adap.
 * @smbus_xfer: Issue smbus transactions to the given I2C adapter. If this
 *   is not present, then the bus layer will try and convert the SMBus calls
 *   into I2C transfers instead.
 * @functionality: Return the flags that this algorithm/adapter pair supports
 *   from the I2C_FUNC_* flags.
 * @reg_slave: Register given client to I2C slave mode of this adapter
 * @unreg_slave: Unregister given client from I2C slave mode of this adapter
 *
 * The following structs are for those who like to implement new bus drivers:
 * i2c_algorithm is the interface to a class of hardware solutions which can
 * be addressed using the same bus algorithms - i.e. bit-banging or the PCF8584
 * to name two of the most common.
 *
 * The return codes from the @master_xfer field should indicate the type of
 * error code that occurred during the transfer, as documented in the kernel
 * Documentation file Documentation/i2c/fault-codes.
 */
struct i2c_algorithm {
	/* If an adapter algorithm can't do I2C-level access, set master_xfer
	   to NULL. If an adapter algorithm can do SMBus access, set
	   smbus_xfer. If set to NULL, the SMBus protocol is simulated
	   using common I2C messages */
	/* master_xfer should return the number of messages successfully
	   processed, or a negative value on error */
	int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs,
			   int num);  
    //---------------(A)
        
	int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr,
			   unsigned short flags, char read_write,
			   u8 command, int size, union i2c_smbus_data *data);
    //---------------(B)
	/* To determine what the adapter supports */
	u32 (*functionality) (struct i2c_adapter *);
    //---------------(C)
    
#if IS_ENABLED(CONFIG_I2C_SLAVE)
	int (*reg_slave)(struct i2c_client *client);
	int (*unreg_slave)(struct i2c_client *client);
#endif
};

(A)master_xfer 是控制器执行 I2C 传输的核心函数,里面有一个关键的参数就是 struct i2c_msg *msgs, 驱动程序会通过该函数与 I2C 设备通信,具体的讲解下文会单独讲;参三num是指该msgs数据的长度。

(B)smbus_xferSMBUS有关的数据传输接口,如果为NULL,I2C core会尝试使用master_xfer模拟

(C)functionality该函数返回适配器支持的功能标志,用于描述适配器能够支持哪些类型的 I2C 或 SMBus 操作:

  • I2C_FUNC_I2C: 适配器支持基本的 I2C 功能。
  • I2C_FUNC_10BIT_ADDR: 支持 10 位地址的 I2C 设备。
  • I2C_FUNC_PROTOCOL_MANGLING: 支持非标准协议行为(如时序微调等)。
  • I2C_FUNC_NOSTART: 支持不需要发送 START 信号的 I2C 传输。
  • I2C_FUNC_SMBUS_*: 支持 SMBus 协议的各种操作,如字节传输、块传输等。

4.struct i2c_msg

用于描述 I2C 传输过程中一次消息(msg)的内容。I2C 通信通常以消息为单位进行操作,一个 i2c_msg 结构体对应 I2C 总线上的一次传输,无论是主机向从机发送数据,还是主机从从机读取数据

\Linux-4.9.88\include\uapi\linux\i2c.h
struct i2c_msg {
	__u16 addr;	/* slave address			*/
	__u16 flags;
#define I2C_M_RD		0x0001	/* read data, from slave to master */
					/* I2C_M_RD is guaranteed to be 0x0001! */
#define I2C_M_TEN		0x0010	/* this is a ten bit chip address */
#define I2C_M_RECV_LEN		0x0400	/* length will be first received byte */
#define I2C_M_NO_RD_ACK		0x0800	/* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_IGNORE_NAK	0x1000	/* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_REV_DIR_ADDR	0x2000	/* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_NOSTART		0x4000	/* if I2C_FUNC_NOSTART */
#define I2C_M_STOP		0x8000	/* if I2C_FUNC_PROTOCOL_MANGLING */
	__u16 len;		/* msg length				*/
	__u8 *buf;		/* pointer to msg data			*/
};

(1)addr,I2C slave device的地址。

(2)flags,数据传输可携带的flag,下面讲解

(3)len,数据传输的长度,单位为byte。

(4)buf,数据buf。

正常写:

S Addr Wr [A] Data [A] Data [A] ... [A] Data [A] P
  • 主设备发送 START 信号,接着发送从设备地址(写操作标志位 Wr),等待应答 A,然后发送数据,直到发送完成并收到应答 A,最后发送 STOP 信号。

正常读:

S Addr Rd [A] [Data] A [Data] A ... A [Data] NA P
  • 主设备发送 START 信号,接着发送从设备地址(读操作标志位 Rd),等待应答 A,然后从从设备读取数据,直到读取完成并返回 NACK(表示没有更多数据可读),然后发送 STOP 信号。

读写混合操作:

  • 读写混合操作通常出现在需要连续传输的场景中。比如先从设备读取数据,再发送某些写入命令:
S Addr Rd [A] [Data] NA S Addr Wr [A] Data [A] P

flag:

  • I2C_M_RD(0x0001):表示这是一个读操作,数据流向是从从设备到主设备。默认情况下,没有这个标志时,消息是写操作(主设备向从设备发送数据)。
  • I2C_M_TEN(0x0010):表示从设备使用的是 10 位地址。默认情况下,I2C 使用 7 位地址。
  • I2C_M_RECV_LEN(0x0400): 表示读取的数据长度将由从设备通过第一个接收到的字节来指定。
  • I2C_M_NO_RD_ACK(0x0800):表示在读取过程中不需要确认(ACK)忽略所有的NACK/ACK信号。这个标志位常见于 SMBus(System Management Bus)设备。某些设备在 I2C 读操作的开始,会首先发送一个字节作为接下来的数据长度,然后再传输实际的数据。
  • I2C_M_IGNORE_NAK(0x1000):表示即使在收到非应答(NAK,No Acknowledgement)信号后,也要继续执行传输操作。 某些从设备设计不规范,在正常情况下可能会返回 NACK,即使仍然有数据可以读取。使用此标志时,主设备会继续读取数据,而不会因为 NACK 停止传输。例如,读取电视的 EDID 信息时,可能会遇到这样的设备。
  • I2C_M_REV_DIR_ADDR(0x2000): 反转读写方向,即在读操作时发送写信号,写操作时发送读信号。
  • I2C_M_NOSTART(0x4000): 如果消息的标志位中包含 I2C_M_NOSTART,则会跳过 START 信号的发送,直接传输数据。这种场景比较少见,可能在一些特定硬件或者协议优化中用到。例如, 有两个连续的消息
    • 正常情况下:
  S Addr Rd [A] [Data] NA S Addr Wr [A] Data [A] P 
  S Addr Rd [A] [Data] NA S Addr Wr [A] Data [A] P
-  使用 `I2C_M_NOSTART` 后:  
S Addr Rd [A] [Data] NA S Addr Wr [A] Data [A] P 
S Addr Rd [A] [Data] NA Data [A] P
  • I2C_M_STOP(0x8000):表示在本次传输结束时,需要发送一个停止信号(STOP 信号)。如果不设置此标志,可能会继续传输后续消息。仅支持 I2C_FUNC_PROTOCOL_MANGLING 的适配器能使用此标志。

至于i2c client结构体留到 consumer 角度讲一下i2c外设 专节再细讲,只需看框架图中的介绍就行了

标签:i2c,struct,algorithm,adapter,I2C,Data,设备
From: https://blog.csdn.net/caiji0169/article/details/142907145

相关文章

  • 会讲故事的I2C通信时序
    前言:    相信各位在学习STM32时候的I2C通信肯定特别苦恼吧,这是什么通信时序,为什么起始终止发送SCL和SDA要那样,即使是深刻学习理解了一遍,时间长了之后也容易忘记,因为记的都是概念性的东西,枯燥无味的概念文字确实长时间后就容易忘记,那有没有什么方法可以让自己记牢一点......
  • WebSecurityConfigurerAdapter 关于成功之后页面跳转的配置
    packagecom.feitai.auth.config;importcom.feitai.manager.PtfUserDetailsManager;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.context.annotation.Configuration;importorg.springframework.security.config.annota......
  • 2023 Benelux Algorithm Programming Contest (BAPC 23)
    A-\texttt题意\(n\)个软件包,已知大小,可以同时下载\(k\)个,已经下载好了\(m\)个,选\(k\)个下载使得下载完后进度最大,输出已完成进度所占百分比。思路选最大的\(m+k\)个。代码点击查看代码#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongvoid......
  • 解决Windows触摸板频繁失灵问题(I2C HID无法启动 代码10)
    我的电脑是华硕的笔记本,在多年前之前就出现偶尔的触摸板失灵的情况,那时候在官网升级驱动啥的也能解决,但是不是长久之计,后来又是经常在网上看教程啥的,终于在今天找到了最好用的方法,没有之一,绝对是目前最有效,最好的解决方法,也是参考了别人的文章,结合自己的实际情况而总结。话不多......
  • 实现远距离通信 PS304数字接口转发器实现UART转换为I2C、SPI、1Wire等多种数字接口!
    实现远距离通信PS304数字接口转发器实现UART转换为I2C、SPI、1Wire等多种数字接口!PS304多种数字接口物理层协议转发器,能够实现UART转换为I2C、SPI、1Wire等其他数字接口,以实现远距离通信。该转发器具备内嵌磁隔离双电源及辅助增强电源电路、自适应线缆算法和强大灵活的S2S协议......
  • CRICOS Data Structures and AlgorithmsHash Tables
    DataStructuresandAlgorithmsHashTablesPage1of3CRICOSProvideCode:00301J Note:hashArraystoresthekey,valueandstate(used,free,orpreviously-used)ofeveryhashEntry.WemuststoreboththekeyandvaluesinceweneedtocheckhashArrayto......
  • 在C#中使用适配器Adapter模式和扩展方法解决面向的对象设计问题
    之前有阵子在业余时间拓展自己的一个游戏框架,结果在实现的过程中发现一个设计问题。这个游戏框架基于MonoGame实现,在MonoGame中,所有的材质渲染(TextureRendering)都是通过SpriteBatch类来完成的。举个例子,假如希望在屏幕的某个地方显示一个图片材质(imageTexture),就在Game类的子类的D......
  • comp10002 Foundations of Algorithms
    comp10002 Foundations of AlgorithmsSemester 2,2024Assignment 2LearningOutcomesInthisproject,youwilldemonstrateyour understanding ofdynamic memory and linked data structures (Chap- ter 10) and extend your program design, testi......
  • Study Plan For Algorithms - Part48
    1.不同的二叉搜索树II给定一个整数n,请生成并返回所有由n个节点组成且节点值从1到n互不相同的不同二叉搜索树。classSolution:defgenerateTrees(self,n:int)->List[Optional[TreeNode]]:ifn==0:return[]returnself.g......
  • 带I2C的LCD12864使用经验总结和例程(RSCG12864B)
    搬运说明:本文是本人在24年4月CSDN上发布的,现全文搬运至博客园,图片水印暂未去除,并删除原CSDN博文。本文简要说明了带I2C协议的LCD12864屏幕的使用经验与教训,特别是厂家说明书说法有误或未提及的内容。文末也提供一个本人编写的STC89C52单片机读取SHT30温湿度传感器并显示在LCD1286......