| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 系统运维 -> IIC驱动 -> 正文阅读 |
|
[系统运维]IIC驱动 |
参考这个大神:28.Linux-IIC驱动(详解) - 诺谦 - 博客园 1. I2C体系结构分析 1.1首先进入linux内核的driver/i2c目录下,如下图所示: ?其中重要的文件介绍如下: 1)algos文件夹(algorithms) 里面保存I2C的通信方面的算法 2)busses文件夹 里面保存I2C总线驱动相关的文件,比如i2c-omap.c、 i2c-versatile.c、 i2c-s3c2410.c等。 3)?chips文件夹 里面保存I2C设备驱动相关的文件 4)?i2c-core.c 这个文件实现了I2C核心的功能(I2C总线的初始化、注册和适配器添加和注销等相关工作) 5)?i2c-dev.c 提供了通用的read( ) 、 write( ) 和ioctl( ) 等接口,实现了I2C适配器设备文件的功能,其中I2C设备的主设备号都为89, 次设备号为0~255。 显然,它和前几次驱动类似, I2C也分为总线驱动和设备驱动,总线就是协议相关的,它知道如何收发数据,但不知道数据含义,设备驱动却知道数据含义 1.2 I2C驱动架构,如下图所示:
如上图所示,每一条I2C对应一个adapter适配器,在kernel中, adapter适配器是通过struct adapter结构体定义,主要是通过i2c core层将i2c设备与i2c adapter关联起来。 2.分析I2C总线驱动 参考 drivers/i2c/busses/i2c-s3c2410.c 先进入init入口函数,如下图所示: 在init函数中,注册了一个?“s3c2440-i2c”的platform_driver平台驱动,来看看probe函数做了些什么: 进入s3c24xx_i2c_probe函数:
其中i2c_adapter结构体是放在s3c24xx_i2c->adap,如下图所示: i2c_register_adapter()函数代码如下所示:
在i2c_register_adapter()函数里主要执行以下几步: ①将adapter放入i2c_bus_type的adapter链表 ②i2c_adapter表示物理上的一个i2C设备(适配器), 在i2c-s3c2410.c中,是存放在s3c24xx_i2c结构体下的(struct ?i2c_adapter ?adap)成员中 ③将所有的i2c设备调出来,执行i2c_driver设备的attach_adapter函数来匹配 其中, i2c_driver结构体会在后面讲述到,显然IIC总线驱动i2c-s3c2410.c,主要设置适配器adapter,然后注册适配器,里面帮我们做好了IIC通信的架构,就是不知道发什么内容。 3.分析IIC设备驱动 参考: driver/i2c/chips/eeprom.c 先来看它的init入口函数:
?其中struct ?i2c_driver? eeprom_driver的成员如下:
显然,在init函数中通过i2c_add_driver()注册i2c_driver结构体,然后通过i2c_driver ->attach_adapter来匹配内核中的各个总线驱动的适配器, 发送这个设备地址,若有ACK响应,表示匹配成功。 接下来,我们进入i2c_add_driver()来看看是不是这样的:
在i2c_add_driver ()函数里主要执行以下几步: ①放入到i2c_bus_type链表 ②取出adapters链表中所有的i2c_adapter,然后执行i2c_driver->attach_adapter() 所以i2c_adapter适配器和i2c_driver设备驱动注册框架如下所示:
这里调用了i2c_driver ->attach_adapter(adapter),我们看看里面是不是通过发送IIC设备地址,等待ACK响应来匹配的。 以struct i2c_driver eeprom_driver 为例,进入i2c_driver ->eeprom_attach_adapter()函数:
如下图所示,里面调用了i2c_probe(adapter, &addr_data, eeprom_detect)函数: 上图的第1个参数就是i2c_adapter适配器,第2个参数addr_data变量,里面存放了IIC设备地址的信息,第3个参数eeprom_detect就是具体的设备探测回调函数i2c_probe()函数,会通过adapter适配器发送IIC设备地址addr_data,如果收到ACK信号,就调用eeprom_detect()回调函数来注册i2c_client结构体,该结构体对应真实的物理从设备,而i2c_driver对应的是设备驱动,也就是说,只有当适配器支持这个设备驱动,才会注册i2c_client从设备。 而在i2c_driver ->detach_client()中,则注销i2c_client结构体 其中addr_data变量是struct i2c_client_address_data结构体,它的成员如下所示:
当上面结构体的数组成员以I2C_CLIENT_END结尾,则表示地址已结束,比如at24c02设备为例,看这个结构体如何定义的:
所以在i2c_driver ->attach_adapter(adapter)函数里主要执行以下几步: 1)?调用?i2c_probe(adap,?i2c_client_address_data设备地址结构体, 回调函数); 2)?将要发的设备地址结构体打包成i2c_msg, 3)?然后执行i2c_transfer()来调用i2c_adapter->algo->master_xfer()将i2c_msg发出去 4)若收到ACK回应,便进入回调函数,注册i2c_client从设备,使该设备与适配器联系在一起 所以适配器和iic设备驱动最终注册框架图如下所示: 参考driver/i2c/chips/eeprom.c驱动,来写出24C02驱动以及测试程序 驱动代码步骤如下: 1.定义file_operations结构体 ,设置字符设备的读写函数(实现对24C02的读写操作) 2.定义i2c_client_address_data结构体,里面保存24C02的设备地址 3.?定义一个i2c_driver驱动结构体 4.写回调函数,里面注册i2c_client,字符设备( 字符设备用来实现读写24C02里的数据) 5.?写init入口函数,exit出口函数 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 | -2024/12/25 14:59:10- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |
数据统计 |