I2C驱动(九) -- i2c_adapter控制器驱动框架编写

相关文章

I2C驱动(一) – I2C协议
I2C驱动(二) – SMBus协议
I2C驱动(三) – 驱动中的几个重要结构
I2C驱动(四) – I2C-Tools介绍
I2C驱动(五) – 通用驱动i2c-dev.c分析
I2C驱动(六) – I2C驱动程序模型
I2C驱动(七) – 编写I2C设备驱动之i2c_driver
I2C驱动(八) – 编写I2C设备驱动之i2c_client

文章目录

  • 相关文章
  • 参考资料
  • 一、回顾
    • 1.1 I2C驱动程序的层次
    • 1.2 I2C总线-设备-驱动模型
  • 二、I2C_Adapter驱动框架
    • 2.1 重要结构
    • 2.2 驱动程序框架
  • 三、总结


参考资料

  • Linux内核文档:
    • Linux-4.9.88\Documentation\devicetree\bindings\i2c\i2c-gpio.txt
  • Linux内核驱动程序:使用GPIO模拟I2C
    • Linux-4.9.88\drivers\i2c\busses\i2c-gpio.c
  • Linux内核真正的I2C控制器驱动程序
    • IMX6ULL: Linux-4.9.88\drivers\i2c\busses\i2c-imx.c

一、回顾

1.1 I2C驱动程序的层次

在这里插入图片描述
假设有一个epprom设备,应用层想要往里写 “abc” 三个字符,步骤如下:
(1)应用层
应用层就是个大爷,他不管底层怎么实现,他只调用write往里写“abc”.
(2)i2c设备驱动层
设备驱动层,知道要怎么发,他会分3次往里写:

  • S 0x50 0x0 ‘a’ p //发出start信号,往设备地址0x50的寄存器0x0写入’a’,发出停止信号p
  • S 0x50 0x1 ‘a’ p
  • S 0x50 0x2 ‘a’ p

(3)核心层
抽象出一些通用接口,辅助实现传输
(4)控制器层
真正做i2c读写操作

1.2 I2C总线-设备-驱动模型

在这里插入图片描述
前面我们已经分析知道i2c设备驱动基于i2c总线-设备-驱动模型,可以分为i2c_clienti2c_driver两边,并分别讲述了二者的编写过程。其中i2c_client结构中包含一个i2c_adapter类型变量,也就是这个i2c设备对应的控制器。下面介绍i2c_adapter的框架和编写过程。

二、I2C_Adapter驱动框架

2.1 重要结构

(1)i2c_adapter
它代表一个i2c控制器,最重要的两个成员:*algo 里面提供了各种传输函数;nr表示第几条i2c总线。

struct i2c_adapter {
... 
	const struct i2c_algorithm *algo; //i2c算法,里面包含有传输函数
...
	int nr; //表示第几条i2c总线
...
};

(2)i2c_algorithm

struct i2c_algorithm {
	/* 这是最重要的函数,它实现了一般的I2C传输,用来传输一个或多个i2c_msg */
	int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs,
			   int num);
	/* 实现SMBus传输,如果不提供这个函数,SMBus传输会使用master_xfer来模拟 */		   
	int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr,
			   unsigned short flags, char read_write,
			   u8 command, int size, union i2c_smbus_data *data);
	/* 返回所支持的flags:各类I2C_FUNC_* */
	u32 (*functionality) (struct i2c_adapter *);

#if IS_ENABLED(CONFIG_I2C_SLAVE)
	/* 有些I2C Adapter也可工作与Slave模式,用来实现或模拟一个I2C设备
	* reg_slave就是让把一个i2c_client注册到I2C Adapter,换句话说就是让这	
	* 个I2C Adapter模拟该i2c_client; unreg_slave:反注册
 	*/
	int (*reg_slave)(struct i2c_client *client);
	int (*unreg_slave)(struct i2c_client *client);
#endif
};

2.2 驱动程序框架

(1)怎么写驱动?

还是一样的套路:分配、设置、注册i2c_adapter结构体:

  • i2c_adapter的核心是i2c_algorithm
  • i2c_algorithm的核心是master_xfer

(2)在哪里分配、设置、注册i2c_adapter结构体?

使用万能的驱动程序结构:platform总线-设备-驱动模型,和i2c总线-设备-驱动模型是同一个道理,程序分为platform_deviceplatform_driver两边,platform_device 也可以是设备树定义,二者进行匹配,成功就调用probe函数。probe函数中我们分配、设备、注册一个i2c_adpater结构体
在这里插入图片描述
(3)编写程序
1. 添加设备树
在根节点下添加

/{
	i2c-bus-virtual{
		compatible = "100ask, i2c-bus-virtual";
	};
}

2. 编写i2c_adapter驱动框架
参考gpio-i2c.c

#include <linux/completion.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c-algo-bit.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_data/i2c-gpio.h>
#include <linux/platform_device.h>
#include <linux/slab.h>

static struct i2c_adapter *g_adapter;

/* 核心:传输函数 */
static int i2c_bus_virtual_master_xfer(struct i2c_adapter *i2c_adap,
		    struct i2c_msg msgs[], int num)
{
	int i;

	for (i = 0; i < num; i++)
	{
		// do transfer msgs[i];
	}
	
	return num;
}

/* 返回可支持的功能函数 */
static u32 i2c_bus_virtual_func(struct i2c_adapter *adap)
{
	return I2C_FUNC_I2C | I2C_FUNC_NOSTART | I2C_FUNC_SMBUS_EMUL |
	       I2C_FUNC_SMBUS_READ_BLOCK_DATA |
	       I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
	       I2C_FUNC_PROTOCOL_MANGLING;
}


const struct i2c_algorithm i2c_bus_virtual_algo = {
	.master_xfer   = i2c_bus_virtual_master_xfer,
	.functionality = i2c_bus_virtual_func,
};


static int i2c_bus_virtual_probe(struct platform_device *pdev)
{
	/* 从设备树获得信息,设置i2c_adapter,例如频率等等  */
	
	/* 分配, 设置, 注册 i2c_adapter */
	g_adapter = kzalloc(sizeof(*g_adapter), GFP_KERNEL);

	g_adapter->owner = THIS_MODULE;
	g_adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
	g_adapter->nr = -1;
	snprintf(g_adapter->name, sizeof(g_adapter->name), "i2c-bus-virtual");

	g_adapter->algo = &i2c_bus_virtual_algo;

	i2c_add_adapter(g_adapter);  //不管adap->nr原来是什么,都动态设置adap->nr

	// i2c_add_numbered_adapter(g_adapter); //如果adap->nr == -1 则动态分配nr; 否则使用该nr 
	
	return 0;
}

static int i2c_bus_virtual_remove(struct platform_device *pdev)
{
	i2c_del_adapter(g_adapter);
	return 0;
}

static const struct of_device_id i2c_bus_virtual_dt_ids[] = {
	{ .compatible = "100ask,i2c-bus-virtual", },
	{ /* sentinel */ }
};

/* 构造platform_driver结构体 */
static struct platform_driver i2c_bus_virtual_driver = {
	.driver		= {
		.name	= "i2c-bus-virtual",
		.of_match_table	= of_match_ptr(i2c_bus_virtual_dt_ids),
	},
	.probe		= i2c_bus_virtual_probe,
	.remove		= i2c_bus_virtual_remove,
};

/* 入口函数 */
static int __init i2c_bus_virtual_init(void)
{
	int ret;

    /* 注册platform_driver结构 */
	ret = platform_driver_register(&i2c_bus_virtual_driver);
	if (ret)
		printk(KERN_ERR "i2c-gpio: probe failed: %d\n", ret);

	return ret;
}
/*出口函数 */
static void __exit i2c_bus_virtual_exit(void)
{
    /* 卸载platform_driver结构 */
	platform_driver_unregister(&i2c_bus_virtual_driver);
}
module_init(i2c_bus_virtual_init);
module_exit(i2c_bus_virtual_exit);

MODULE_AUTHOR("zhongpz");
MODULE_LICENSE("GPL");

三、总结

本文介绍了i2c_adapter的结构和编写步骤,并编写出了驱动框架。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/979799.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

分布式系统核心基石:CAP定理、BASE理论与一致性算法深度解析

一、CAP定理&#xff1a;分布式系统的设计边界 1.1 核心定义与经典三角 CAP定理&#xff08;Brewers Theorem&#xff09;指出&#xff0c;在分布式系统中&#xff0c;一致性&#xff08;Consistency&#xff09;、可用性&#xff08;Availability&#xff09;、分区容错性&a…

3 算法1-4 过河卒

题目描述 棋盘上 A 点有一个过河卒&#xff0c;需要走到目标 B 点。卒行走的规则&#xff1a;可以向下、或者向右。同时在棋盘上 C 点有一个对方的马&#xff0c;该马所在的点和所有跳跃一步可达的点称为对方马的控制点。因此称之为“马拦过河卒”。 棋盘用坐标表示&#xff…

AutoMQ:无需 Cruise Control 实现 Kafka 的自动分区再平衡

导读&#xff1a;AutoMQ是一款贯彻云优先理念来设计的 Kafka 替代产品。AutoMQ 创新地对 Apache Kafka 的存储层进行了基于云的重新设计&#xff0c;在 100% 兼容 Kafka 的基础上通过将持久性分离至 EBS 和 S3 带来了 10x 的成本降低以及 100x 的弹性能力提升&#xff0c;并且相…

论文阅读之基于Syn2Real域的侧扫声纳类水雷目标探测

摘要 由于现实世界数据的稀缺性&#xff0c;基于深度学习的水下水雷探测受到了限制。这种稀缺性导致过拟合&#xff0c;即模型在训练数据上表现良好&#xff0c;但在未见数据上表现不佳。本文提出了一种使用扩散模型的Syn2Real &#xff08;Synthetic to Real&#xff09;域泛…

如何使用Docker搭建哪吒监控面板程序

哪吒监控(Nezha Monitoring)是一款自托管、轻量级的服务器和网站监控及运维工具,旨在为用户提供实时性能监控、故障告警及自动化运维能力。 文档地址:https://nezha.wiki/ 本章教程,使用Docker方式安装哪吒监控面板,在此之前,你需要提前安装好Docker. 我当前使用的操作系…

微服务学习(1):RabbitMQ的安装与简单应用

目录 RabbitMQ是什么 为什么要使用RabbitMQ RabbitMQ的安装 RabbitMQ架构及其对应概念 队列的主要作用 交换机的主要作用 RabbitMQ的应用 通过控制面板操作&#xff08;实现收发消息&#xff09; RabbitMQ是什么 RabbitMQ是一个开源的消息队列软件&#xff08;消息代理…

综合实验处理表格

新建excel表格&#xff0c;输入信息&#xff0c;另存为csv文件。 利用notepad打开csv文件&#xff0c;可以观察格式 目标&#xff1a;通过编程处理文件&#xff0c;实现对数据的处理&#xff0c;成绩求和以及评价 对数据逐行处理&#xff0c;读一行&#xff0c;处理一行&#…

【leetcode hot 100 560】和为K的子数组

解法一&#xff1a;用左右指针寻找字串&#xff0c;如果和>k&#xff0c;则减少一个数&#xff08;left&#xff09;&#xff1b;如果和<k&#xff0c;则加上一个数&#xff08;right&#xff09;。 class Solution {public int subarraySum(int[] nums, int k) {int nu…

STM32CubeMx DRV8833驱动

一、DRV8833驱动原理 ​ STBY口接单片机的IO口&#xff0c;STBY置0电机全部停止&#xff0c;置1才能工作。STBY置1后通过AIN1、AIN2、BIN1、BIN2 来控制正反转。 AIN1AIN2电机状态00停止1speed反转speed1正转11停止 其中A端&#xff08;AIN1与AIN2&#xff09;只能控制AO1与…

Android 图片压缩详解

在 Android 开发中,图片压缩是一个重要的优化手段,旨在提升用户体验、减少网络传输量以及降低存储空间占用。以下是几种主流的图片压缩方法,结合原理、使用场景和优缺点进行详细解析。 效果演示 直接先给大家对比几种图片压缩的效果 质量压缩 质量压缩:根据传递进去的质…

JavaWeb后端基础(3)

原打算把Mysql操作数据库的一些知识写进去&#xff0c;但是感觉没必要&#xff0c;要是现在会的都是简单的增删改查&#xff0c;所以&#xff0c;这一篇&#xff0c;我直接从java操作数据库开始写&#xff0c;所以这一篇大致就是记一下JDBC、MyBatis、以及SpringBoot的配置文件…

ArcGIS Pro技巧实战:高效矢量化天地图地表覆盖图

在地理信息系统&#xff08;GIS&#xff09;领域&#xff0c;地表覆盖图的矢量化是一项至关重要的任务。天地图作为中国国家级的地理信息服务平台&#xff0c;提供了丰富且详尽的地表覆盖数据。然而&#xff0c;这些数据通常以栅格格式存在&#xff0c;不利于进行空间分析和数据…

TP-LINK路由器如何设置网段、网关和DHCP服务

目标 ①将路由器的网段由192.168.1.XXX改为192.168.5.XXX ②确认DHCP是启用的&#xff0c;并将DHCP的IP池的范围设置为排除自己要手动指定的IP地址&#xff0c;避免IP冲突。 01-复位路由器 路由器按住复位键10秒以上进行重置操作 02-进入路由器管理界面 电脑连接到路由器&…

基于Spring Boot的供应商管理系统设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…

大模型WebUI:Gradio全解12——LangChain原理、架构和组件(3)

大模型WebUI:Gradio全解12——LangChain原理、架构和组件(3) 前言本篇摘要12. LangChain原理及agents构建Gradio UI12.3 LangChain架构12.3.1 LangChain12.3.2 Integration Packages1. 概念2. 示例12.3.3 LangGraph1. 概念2. 示例12.3.4 LangGraph Platform1. 概览2. 优势分…

通过 PromptTemplate 生成干净的 SQL 查询语句并执行SQL查询语句

问题描述 在使用 LangChain 和 Llama 模型生成 SQL 查询时&#xff0c;遇到了 sqlite3.OperationalError 错误。错误信息如下&#xff1a; OperationalError: (sqlite3.OperationalError) near "sql SELECT Name FROM MediaType LIMIT 5; ": syntax error [SQL: …

【每天认识一个漏洞】url重定向

&#x1f31d;博客主页&#xff1a;菜鸟小羊 &#x1f496;专栏&#xff1a;Linux探索之旅 | 网络安全的神秘世界 | 专接本 | 每天学会一个渗透测试工具 常见应用场景 主要是业务逻辑中需要进行跳转的地方。比如登录处、注册处、访问用户信息、订单信息、加入购物车、分享、收…

SQL命令详解之数据的查询操作

目录 1 简介 2 基础查询 2.1 基础查询语法 2.2 基础查询练习 3 条件查询 3.1 条件查询语法 3.2 条件查询练习 4 排序查询 4.1 排序查询语法 4.2 排序查询练习 5 聚合函数 5.1 一般语法&#xff1a; 5.2 聚合函数练习 6 分组查询 6.1 分组查询语法 6.2 分组查询…

IDEA集成DeepSeek,通过离线安装解决无法安装Proxy AI插件问题

文章目录 引言一、安装Proxy AI1.1 在线安装Proxy AI1.2 离线安装Proxy AI 二、Proxy AI中配置DeepSeek2.1 配置本地部署的DeepSeek&#xff08;Ollama方式&#xff09;2.2 通过第三方服务商提供的API进行配置 三、效果测试 引言 许多开发者尝试通过安装Proxy AI等插件将AI能力…

Spring Boot3+Vue3极速整合: 10分钟搭建DeepSeek AI对话系统(进阶)

Spring Boot3Vue3极速整合: 10分钟搭建DeepSeek AI对话系统(进阶) 前言 在上次实战指南《Spring Boot3Vue2极速整合: 10分钟搭建DeepSeek AI对话系统》引发读者热议后&#xff0c;我通过200真实用户反馈锁定了几个问题进行优化进阶处理&#xff1a; 每次对话都需重复上下文背…