【驱动】I2C驱动分析(三)-关键数据类型

这篇具有很好参考价值的文章主要介绍了【驱动】I2C驱动分析(三)-关键数据类型。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

I2C bus

i2c_bus_type 用于表示 I2C 总线类型。bus_type 是 Linux 内核中用于表示总线类型的结构体,用于管理该类型总线上的设备。

struct bus_type i2c_bus_type = {
	.name		= "i2c",
	.match		= i2c_device_match,
	.probe		= i2c_device_probe,
	.remove		= i2c_device_remove,
	.shutdown	= i2c_device_shutdown,
};
  • .name: 用于指定总线类型的名称。在这里,总线类型的名称被设置为 “i2c”,表示 I2C 总线类型。
  • .match: 匹配设备与总线。
  • .probe: 用于在设备与总线匹配成功后进行设备探测和初始化。
  • .remove: 用于设备从总线上移除时的操作。
  • .shutdown: 用于在系统关机时对设备进行关闭和清理操作。

I2C client

struct i2c_client 结构体用于表示 I2C 设备的客户端,并存储了与该设备相关的各种信息,例如设备的地址、名称、适配器、中断请求等。

struct i2c_client {
	unsigned short flags;		/* div., see below		*/
	unsigned short addr;		/* chip address - NOTE: 7bit	*/
					/* addresses are stored in the	*/
					/* _LOWER_ 7 bits		*/
	char name[I2C_NAME_SIZE];
	struct i2c_adapter *adapter;	/* the adapter we sit on	*/
	struct device dev;		/* the device structure		*/
	int irq;			/* irq issued by device		*/
	struct list_head detected;
#if IS_ENABLED(CONFIG_I2C_SLAVE)
	i2c_slave_cb_t slave_cb;	/* callback for slave mode	*/
#endif
};
  • unsigned short flags: 存储一些标志位。
  • unsigned short addr:表示 I2C 设备的地址。需要注意的是,I2C 设备地址通常只占用 7 个比特,而这里只使用了低 7 个比特来存储地址。
  • char name[I2C_NAME_SIZE]:表示 I2C 设备的名称。I2C_NAME_SIZE 是一个宏定义,表示数组的大小。
  • struct i2c_adapter *adapter: 一个指向 struct i2c_adapter 结构体的指针,表示 I2C 设备所连接的适配器。
  • struct device dev: 一个 struct device 结构体,表示 I2C 设备对应的设备结构。
  • int irq: 设备触发的中断请求(IRQ)。
  • struct list_head detected: 链表头,用于存储已检测到的设备。
  • #if IS_ENABLED(CONFIG_I2C_SLAVE) ... #endif: 这是一个条件编译块,用于在编译时根据是否启用了 I2C 从设备模式来条件地包含代码。在启用了 I2C 从设备模式时,这里会有一个 i2c_slave_cb_t 类型的成员 slave_cb,它是一个用于从设备模式的回调函数。

I2C driver

struct i2c_driver 结构体用于表示 I2C 设备的驱动程序,并存储了与该驱动程序相关的各种函数指针、设备驱动结构、标识符表、设备检测回调函数等。

struct i2c_driver {
	unsigned int class;

	/* Notifies the driver that a new bus has appeared. You should avoid
	 * using this, it will be removed in a near future.
	 */
	int (*attach_adapter)(struct i2c_adapter *) __deprecated;

	/* Standard driver model interfaces */
	int (*probe)(struct i2c_client *, const struct i2c_device_id *);
	int (*remove)(struct i2c_client *);

	/* driver model interfaces that don't relate to enumeration  */
	void (*shutdown)(struct i2c_client *);

	/* Alert callback, for example for the SMBus alert protocol.
	 * The format and meaning of the data value depends on the protocol.
	 * For the SMBus alert protocol, there is a single bit of data passed
	 * as the alert response's low bit ("event flag").
	 */
	void (*alert)(struct i2c_client *, unsigned int data);

	/* a ioctl like command that can be used to perform specific functions
	 * with the device.
	 */
	int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);

	struct device_driver driver;
	const struct i2c_device_id *id_table;

	/* Device detection callback for automatic device creation */
	int (*detect)(struct i2c_client *, struct i2c_board_info *);
	const unsigned short *address_list;
	struct list_head clients;
};
  • unsigned int class: 表示驱动程序的类别。
  • int (*attach_adapter)(struct i2c_adapter *) __deprecated: 通知驱动程序有新的总线出现。
  • int (*probe)(struct i2c_client *, const struct i2c_device_id *): 指向驱动程序的探测函数。当一个新的 I2C 设备与驱动程序匹配时,将调用该函数进行初始化和配置。
  • int (*remove)(struct i2c_client *): 表示驱动程序的移除函数。当一个已经存在的 I2C 设备与驱动程序不再匹配时,将调用该函数进行清理和释放资源。
  • void (*shutdown)(struct i2c_client *):表示驱动程序的关机函数。用于在系统关机时执行一些清理操作。
  • void (*alert)(struct i2c_client *, unsigned int data): 表示驱动程序的警报回调函数。该函数用于处理警报事件,例如 SMBus 警报协议中的警报。
  • int (*command)(struct i2c_client *client, unsigned int cmd, void *arg):一个类似于 ioctl 的命令函数。用于执行特定的设备功能。
  • struct device_driver driver: 一个 struct device_driver 表示 I2C 设备驱动程序对应的设备驱动结构。
  • const struct i2c_device_id *id_table: 一个指向 struct i2c_device_id 结构体的常量指针,用于存储设备的标识符表。
  • int (*detect)(struct i2c_client *, struct i2c_board_info *): 设备检测回调函数,用于自动创建设备。
  • const unsigned short *address_list: 无符号短整型数组的常量指针,用于存储设备的地址列表。
  • struct list_head clients: 链表头,用于存储与该驱动程序关联的客户端列表。

I2C algorithm

在 Linux 内核中,每个 I2C 适配器通常都会有一个对应的 I2C 算法。struct i2c_algorithm 结构体用于表示 I2C 适配器的算法,并存储了与该适配器相关的各种函数指针,用于执行主设备传输、SMBus 传输和功能性查询。

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);
	int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr,
			   unsigned short flags, char read_write,
			   u8 command, int size, union i2c_smbus_data *data);

	/* To determine what the adapter supports */
	u32 (*functionality) (struct i2c_adapter *);

#if IS_ENABLED(CONFIG_I2C_SLAVE)
	int (*reg_slave)(struct i2c_client *client);
	int (*unreg_slave)(struct i2c_client *client);
#endif
};
  • int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs, int num): I2C 主设备传输函数。该函数用于在总线上执行一系列 I2C 消息传输操作,返回成功处理的消息数量,或者在出错时返回负值。
  • int (*smbus_xfer)(struct i2c_adapter *adap, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data *data): 指向 SMBus 传输函数。该函数用于在总线上执行 SMBus 消息传输操作,根据给定的参数执行读取或写入操作,并返回操作结果。
  • u32 (*functionality)(struct i2c_adapter *): 指向功能性函数。该函数用于确定适配器支持的功能,并返回一个表示适配器功能的位掩码。
  • #if IS_ENABLED(CONFIG_I2C_SLAVE) ... #endif: 条件编译块,用于在编译时根据是否启用了 I2C 从设备模式来条件地包含代码。在启用了 I2C 从设备模式时,这里会有两个函数指针 reg_slaveunreg_slave,分别用于注册和注销从设备。

I2C adapter

struct i2c_adapter 结构体用于表示 I2C 适配器,并存储了与适配器相关的各种属性和状态信息,如适配器的拥有者、算法、超时时间、设备等。这些信息用于控制和管理 I2C 总线上的通信和操作。

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	*/
	struct rt_mutex bus_lock;

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

	int nr;
	char name[48];
	struct completion dev_released;

	struct mutex userspace_clients_lock;
	struct list_head userspace_clients;

	struct i2c_bus_recovery_info *bus_recovery_info;
	const struct i2c_adapter_quirks *quirks;
};
  • struct module *owner: 指向拥有该 I2C 适配器的内核模块的指针。
  • unsigned int class: 指定可以进行探测的 I2C 设备类别。
  • const struct i2c_algorithm *algo: 用于访问总线的 I2C 算法的指针。
  • void *algo_data: 存储与 I2C 算法相关的数据。
  • struct rt_mutex bus_lock: 用于保护 I2C 总线的互斥锁。
  • int timeout: I2C 传输的超时时间,以 jiffies 为单位。
  • int retries: 在传输期间发生错误时进行的重试次数。
  • struct device dev: 表示适配器设备的结构体。
  • int nr: 适配器的编号。
  • char name[48]: 适配器的名称。
  • struct completion dev_released: 设备释放的完成量。
  • struct mutex userspace_clients_lock: 保护用户空间客户端列表的互斥锁。
  • struct list_head userspace_clients: 用户空间客户端的链表。
  • struct i2c_bus_recovery_info *bus_recovery_info: I2C 总线恢复信息的指针。
  • const struct i2c_adapter_quirks *quirks: I2C 适配器的特殊属性的指针。

i2c_msg

struct i2c_msg 提供了在 Linux 内核中定义和组织 I2C 消息的方式,通过 I2C 总线与 I2C 设备进行通信。

struct i2c_msg {
	__u16 addr;	/* slave address			*/
	__u16 flags;
#define I2C_M_TEN		0x0010	/* this is a ten bit chip address */
#define I2C_M_RD		0x0001	/* read data, from slave to master */
#define I2C_M_STOP		0x8000	/* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_NOSTART		0x4000	/* if I2C_FUNC_NOSTART */
#define I2C_M_REV_DIR_ADDR	0x2000	/* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_IGNORE_NAK	0x1000	/* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_NO_RD_ACK		0x0800	/* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_RECV_LEN		0x0400	/* length will be first received byte */
	__u16 len;		/* msg length				*/
	__u8 *buf;		/* pointer to msg data			*/
};
  • __u16 addr: I2C 设备的从设备地址。
  • __u16 flags:保存了控制 I2C 消息行为的各种标志。

  • I2C_M_TEN(0x0010):表示从设备地址为十位地址。通常,I2C 设备使用七位地址,但某些设备支持十位地址。

  • I2C_M_RD(0x0001):表示消息是一个读操作,数据从从设备传输到主设备。

  • I2C_M_STOP(0x8000):该标志与 I2C_FUNC_PROTOCOL_MANGLING 特性一起使用。它表示主设备在消息之后应发送停止条件。

  • I2C_M_NOSTART(0x4000):该标志与 I2C_FUNC_NOSTART 特性一起使用。它表示主设备在此消息之前不应生成启动条件。

  • I2C_M_REV_DIR_ADDR(0x2000):该标志与 I2C_FUNC_PROTOCOL_MANGLING 特性一起使用。它表示在传输过程中地址字节应该被反转。

  • I2C_M_IGNORE_NAK(0x1000):该标志与 I2C_FUNC_PROTOCOL_MANGLING 特性一起使用。它表示如果从设备对数据字节发送 NAK(不应答),主设备应忽略它并继续传输。

  • I2C_M_NO_RD_ACK(0x0800):该标志与 I2C_FUNC_PROTOCOL_MANGLING 特性一起使用。它表示如果主设备接收到读传输的最后一个字节,它不应向从设备发送 ACK(应答)位。

  • I2C_M_RECV_LEN(0x0400):该标志表示第一个接收到的字节将包含剩余数据的长度。这通常与 I2C_M_RD 标志结合使用。

  • __u16 len:表示消息的长度,指定主设备和从设备之间要传输的字节数。

  • __u8 *buf:指向存储消息实际数据的数据缓冲区的指针。指针指向存储数据的内存位置。

i2c_board_info

i2c_board_info描述一个I2C设备的板级信息,其中包括设备类型、地址、平台特定数据、体系结构数据、设备树节点、固件节点和中断号等。这些信息可以在设备驱动程序中使用,以便正确地配置和操作I2C设备。

struct i2c_board_info {
	char		type[I2C_NAME_SIZE];
	unsigned short	flags;
	unsigned short	addr;
	void		*platform_data;
	struct dev_archdata	*archdata;
	struct device_node *of_node;
	struct fwnode_handle *fwnode;
	int		irq;
};
  • type:表示I2C设备的类型名称。I2C_NAME_SIZE是一个预定义的常量,表示数组的最大大小。
  • flags:表示与设备相关的标志位。
  • addr:表示I2C设备的地址。
  • platform_data:表示特定于平台的数据。
  • archdata:存储与设备体系结构相关的数据。
  • of_node:表示与设备树相关的节点。这个字段用于与设备树中的节点进行关联。
  • fwnode:表示固件节点(Firmware Node)相关的处理。固件节点是一种用于描述设备和其配置的数据结构,这个字段用于与固件节点进行关联。
  • irq:表示与设备关联的中断号。这个字段用于指示设备在系统中使用的中断。

各结构体的作用与它们之间的关系

i2c_adapter与i2c_algorithm

i2c_adapter对应与物理上的一个适配器,而i2c_algorithm对应一套通信方法,一个i2c适配器需要i2c_algorithm中提供的(i2c_algorithm中的又是更下层与硬件相关的代码提供)通信函数来控制适配器上产生特定的访问周期。缺少i2c_algorithm的i2c_adapter什么也做不了,因此i2c_adapter中包含其使用i2c_algorithm的指针。

i2c_algorithm中的关键函数**master_xfer()**用于产生i2c访问周期需要的start stop ack信号,以i2c_msg(即i2c消息)为单位发送和接收通信数据。

i2c_msg也非常关键,调用驱动中的发送接收函数需要填充该结构体

i2c_driver和i2c_client

i2c_driver对应一套驱动方法,其主要函数是attach_adapter()和detach_client()。i2c_client对应真实的i2c物理设备device,每个i2c设备都需要一个i2c_client来描述。i2c_driver与i2c_client的关系是一对多。一个i2c_driver上可以支持多个同等类型的i2c_client.

i2c_adapter和i2c_client

i2c_adapter和i2c_client的关系与i2c硬件体系中适配器和设备的关系一致,即i2c_client依附于i2c_adapter,由于一个适配器上可以连接多个i2c设备,所以i2c_adapter中包含依附于它的i2c_client的链表。文章来源地址https://www.toymoban.com/news/detail-804910.html

到了这里,关于【驱动】I2C驱动分析(三)-关键数据类型的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • TP驱动——I2C驱动,细节分析——dts设备树

    TP驱动程序,是指带屏幕设备的触屏功能调用的驱动程序。TP外设与主板之间的关系如下框图: 产品常用的屏幕单元为液晶显示屏幕,TP的触摸功能也是一同集成到一起的,通过控制芯片以及外围电路、i2c总线与主板进行通信。 TP驱动的功能逻辑: 当有触点发生时,TP芯片向主

    2024年02月04日
    浏览(43)
  • Linux驱动开发(I2C系统的重要结构体)

    本篇文章来讲解I2C系统的重要结构体,了解这些结构体对于编写I2C驱动来说是至关重要的,所以要想编写好一个I2C驱动程序那么就必须先了解这些结构体。 这里使用百问网的一张图片来讲解: 一个芯片中可以有多个I2C控制器,并且一个I2C控制器可以控制多个设备。那么在对

    2024年02月07日
    浏览(50)
  • Linux驱动开发之i2c框架讲解到例程

            本篇章在rk3399平台上,基于设备树的i2c驱动开发。i2c直接使用硬件i2c总线,体系结构分为3部分:I2C 核心、I2C 总线驱动和I2C 设备驱动。 I2C 核心 (i2c-core.c)提供了I2C 总线驱动和设备驱动的注册、注销方法等。我们主要了解Linux中i2c的基本框架,分为 i2c主机驱动开发

    2024年02月02日
    浏览(45)
  • linux i2c驱动开发之最简单入门:设备树与驱动的匹配

    1在设备树中声明我们的模拟I2C设备: i2c的设备加入是必须放在某个i2c的总线下面的,我们这里是放在 i2c7下面。 可以直接在设备树搜索i2c7,然后把status 修改为okay,然后再加入设备信息. 这里我们指定和驱动匹配的字符串是 myi2c-dev,在bus segment 上分配的地址是 0x70 。 当然这

    2024年02月16日
    浏览(49)
  • Linux设备驱动开发学习笔记(等待队列,锁,字符驱动程序,设备树,i2C...)

    container_of函数可以通过结构体的成员变量检索出整个结构体 函数原型: 内核开发者只实现了循环双链表,因为这个结构能够实现FIFO和LIFO,并且内核开发者要保持最少代码。 为了支持链表,代码中要添加的头文件是linux/list.h。内核中链表实现核心部分的数据结构 是struct li

    2024年01月22日
    浏览(55)
  • 详解AT24CXX驱动开发(linux platform tree - i2c应用)

    目录 概述 1 认识AT24Cxx 1.1 AT24CXX的特性 1.2 AT24CXX描述 1.2.1 引脚 1.2.2 容量描述 1.2.3 设备地址 1.3 操作时序 1.3.1 写单个字节时序 1.3.2 写page字节时序 1.3.3 读取当前数据时序 1.3.4 随机读取数据 1.3.5 连续读取多个数据 2 驱动开发 2.1 硬件接口 2.2 代码实现 2.2.1 查看设备信息 2.2.2 编写

    2024年02月22日
    浏览(47)
  • I2C总线驱动

    SOC芯片平台的外设分为: 一级外设:外设控制器集成在SOC芯片内部 二级外设:外设控制器由另一块芯片负责,通过一些通讯总线与SOC芯片相连 Inter-Integrated Circuit: 字面意思是用于“集成电路之间”的通信总线,简写:IIC(或者I2C) i2c传输的要点就是: 传输一个字节 后面必然

    2024年02月15日
    浏览(42)
  • 【IMX6ULL驱动开发学习】10.Linux I2C驱动实战:AT24C02驱动设计流程

    前情回顾:【IMX6ULL驱动开发学习】09.Linux之I2C框架简介和驱动程序模板_阿龙还在写代码的博客-CSDN博客 目录 一、修改设备树(设备树用来指定引脚资源) 二、编写驱动 2.1 i2c_drv_read 2.2 i2c_drv_write 2.3 完整驱动程序 三、上机测试 放在哪个I2C控制器下面 AT24C02的I2C设备地址(查

    2024年02月11日
    浏览(53)
  • 什么是I2C,I2C怎么用,从实例波形分析I2C读写

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 今天分享的主题是I2C通信。接下来从I2C是什么,怎么用,以及以时钟外设读写作为实例进行分析。 I2C(Inter-Integrated Circuit) ,也可以叫IIC、I2C,译作集成电路总线,是 两线式串行通信总线 ,用于设备

    2024年01月19日
    浏览(58)
  • 嵌入式I2C 信号线为何加上拉电阻(图文并茂)

    IIC 是一个两线串行通信总线,包含一个 SCL 信号和 SDA 信号,SCL 是时钟信号,从主设备发出,SDA 是数据信号,是一个双向的,设备发送数据和接收数据都是通过 SDA 信号。   在设计 IIC 信号电路的时候我们会在 SCL 和 SDA 上加一个上拉电阻。   今天就来分享下,为什么要在

    2024年02月19日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包