Linux I2C framework(1)_概述
作者:wowo 发布于:2016-2-14 22:01 分类:通信类协议
1. 前言
I2C协议是嵌入式系统中广泛使用的一类通信协议,主要用于CPU和各种外设之间的低速数据通信。Linux kernel使用I2C framework抽象、管理相应的资源,并以各种形式,向各类使用者提供API。另外,作为总线(bus)的一种,I2C framework的实现体现了linux设备模型的精髓,值得研究与学习。这就是攥写“Linux I2C framework”系列文章的缘由和目的。
按照分析各类framework的老规矩,蜗蜗会从4个角度分4篇文章介绍I2C framework:
1)Linux I2C framework的整体介绍,包括基础知识、软件框架、API汇整等。就是本文。
2)从Provider的角度,介绍怎么借助I2C framework管理I2C相关的SOC资源。换句话说,就是怎么编写一个I2C driver。具体可参考“Linux I2C framework(2)_I2C provider”。
3)从Consumer的角度,介绍I2C framework为使用者提供了哪些功能、哪些API,以及怎样利用I2C framework编写程序。具体可参考“Linux I2C framework(3)_I2C consumer”。
4)从内部实现的角度,分析I2C framework的实现逻辑。具体可参考“Linux I2C framework(4)_I2C core”。
2. I2C的总线拓扑
图片1 I2C H/W topology
关于I2C的硬件拓扑,相信驱动工程师都很熟悉,这里就不过多描述了,但有一点要强调:
我们都知道,I2C协议是主从式的,包括master(主设备)和slave(从设备),而Linux kernel的I2C framework只抽象了I2C master有关的功能,换句话说,linux kernel有这样的一个假设:
所有运行linux kernel的设备,在I2C总线里面,都是I2C master(至于I2C slave,抱歉,kernel不管!)。
正是基于这样的假设,linux I2C framework才成为当前的样子,具体可参考本文后续的描述。
linux kernel I2C framework使用如下的软件拓扑抽象I2C硬件(我们可以一起领会一下其中的“设备模型”思想):
图片2 I2C S/W topology
1)platform bus(/sys/bus/platform)是驱动工程师常见的bus,用于挂载和CPU通过系统总线连接的各类外设。在I2C framework中,I2C控制器直接从属于platform bus,我们在linux kernel中常说的I2C driver,都是指I2C controller driver,都是以platform driver的形式存在,当然,对应的控制器是platform device。
2)与此同时,kernel抽象出I2C bus(/sys/bus/i2c),用于挂载和I2C controller通过I2C总线连接的各个I2C slave device。
3)比较特殊的地方是,I2C core使用一个虚拟实体----I2C adapter,抽象I2C controller有关的功能(主要是数据的收发),I2C adapter也挂载在I2C bus上。
4)I2C adapter和I2C slave device都挂载在I2C bus上,就可以方便的进行Master(I2C adapter)和Slave之间的匹配操作,并通过I2C core提供的统一接口,访问I2C salve device,进行数据的收发。
5)以上各实体在sysfs中的位置,已经在“图片2”中通过红色字体标注,大家可自行理解。
3. 软件框架
基于第2章所述的总线拓扑,Linux kernel抽象出如下的软件框架:
图片3 I2C framework software architecture
1)I2C framework的最终目标,是提供一种“访问I2C slave devices”的方法。由于这些slave devices由I2C controller控制,因而主要由I2C controller驱动实现这一目标。
2)经过I2C framework的抽象,consumer可以不用关心I2C总线的技术细节,只需要通过简单的API,就可以与slave devices进行数据交互。正常情况下,consumer是位于内核态的其它driver(如HDMI driver、touch screen driver等等)。与此同时,I2C framework也通过字符设备向用户空间提供类似的接口,用户空间程序可以通过该接口访问slave devices。
3)在I2C framework内部,有I2C core、I2C busses、I2C algos和I2C muxes四个模块。
4)I2C core使用I2C adapter和I2C algorithm两个子模块抽象I2C controller的功能,使用I2C client和I2C driver抽象I2C slave device的功能(对应设备模型中的device和device driver)。另外,基于I2C协议,通过smbus模块实现SMBus(System Management Bus,系统管理总线)的功能。
5)I2C busses是各个I2C controller drivers的集合,位于drivers/i2c/busses/目录下,驱动工程师常说的“I2C driver”就是指它们。
6)I2C algos包含了一些通用的I2C algorithm,所谓的algorithm,是指I2C协议包的生成方法,进而组合成I2C的read/write指令,一般情况下,都是由硬件实现,不需要特别关注该目录。
7)I2C muxes用于实现I2C bus的多路复用功能,属于奇葩的冷门功能,暂不过多介绍。
4. I2C有关的软件流程总结
TODO(会在后续文章完成之后再回来补充)。
原创文章,转发请注明出处。蜗窝科技,www.wowotech.net。
标签: Linux Architecture framework I2C

评论:
2016-03-28 19:31
2016-03-28 21:58
2016-03-29 09:01
即便是有了I2C slave device的支持(类似USB 的gadget driver),实际上仍然用struct i2c_client来抽象这个slave设备。
最后:我们觉得我们还是锁定一个内核版本好了,我建议是4.4.y的内核版本,大家都围绕这个版本讨论。
2016-03-28 19:19
我感觉I2C algos和I2C buses模块的关系不是平行关系,毫无疑问,I2C buses模块(I2C controller driver)模块是和底层硬件相关的,所有和具体的I2C controller的交互都是通过I2C busses模块进行,I2C algos是和硬件无关的(也不能这么说,应该说是和硬件操作序列有关)。I2C algos对底层硬件的操作都是通过I2C busses中的adapter的callback完成的,或者说,adapter提供了最底层的通信机制,不同的algos可以利用它实现具体的I2C的数据传输服务。
2016-03-28 21:52
2016-03-29 09:04
2016-03-28 18:54
------------------------------------------
为什么不管呢?其实只要有需求,就应该提供支持的。在4.4.6的内核中,已经增加了对I2C slave的支持,同时也复用了当前的I2C framework的代码。
另外,I2C物理拓扑(图片1)以及关于I2C和设备模型那部分(图片2),基本上四着眼于嵌入式平台,其实可以更通用一些。另外,图片2中的CPU block的出现容易误导的,或者建议增加更多的文字描述,对于I2C和设备模型之间的关系可以多写一些。
2016-03-28 21:47
通用一些具体指什么意思呢?加入slave?还是其它?
2016-03-29 08:50
增加slave的支持是指其他的模块可以调用i2c core提供的i2c_slave_register/i2c_slave_unregister来注册一个或者注销一个i2c的slave设备。一旦注册了slave设备,底层的adapter要切换到slave mode。完成这些操作之后,该i2c slave设备可以响应来自对端i2c master设备的各种命令和数据了。
2016-03-04 22:05
2016-02-19 15:34
我们讲的在用户空间访问,只是应用程序通过I2C Framework提供的字符设备接口,访问I2C slave device(数据收发)而已,应该不需要关心中断。
2016-02-19 16:52
是的,是在应用程序中通过字符设备接口open/read/write数据到slave device,这样做发数据没问题,但是收数据需要while循环去读或者poll去查询是否有数据可读。我想知道有没有办法把kernel的有数据可接受这个中断暴露给userspace的应用程序?这样应用程序只在这个中断来了之后才去度slave device的数据。
功能
最新评论
文章分类
随机文章
文章存档
- 2024年2月(1)
- 2023年5月(1)
- 2022年10月(1)
- 2022年8月(1)
- 2022年6月(1)
- 2022年5月(1)
- 2022年4月(2)
- 2022年2月(2)
- 2021年12月(1)
- 2021年11月(5)
- 2021年7月(1)
- 2021年6月(1)
- 2021年5月(3)
- 2020年3月(3)
- 2020年2月(2)
- 2020年1月(3)
- 2019年12月(3)
- 2019年5月(4)
- 2019年3月(1)
- 2019年1月(3)
- 2018年12月(2)
- 2018年11月(1)
- 2018年10月(2)
- 2018年8月(1)
- 2018年6月(1)
- 2018年5月(1)
- 2018年4月(7)
- 2018年2月(4)
- 2018年1月(5)
- 2017年12月(2)
- 2017年11月(2)
- 2017年10月(1)
- 2017年9月(5)
- 2017年8月(4)
- 2017年7月(4)
- 2017年6月(3)
- 2017年5月(3)
- 2017年4月(1)
- 2017年3月(8)
- 2017年2月(6)
- 2017年1月(5)
- 2016年12月(6)
- 2016年11月(11)
- 2016年10月(9)
- 2016年9月(6)
- 2016年8月(9)
- 2016年7月(5)
- 2016年6月(8)
- 2016年5月(8)
- 2016年4月(7)
- 2016年3月(5)
- 2016年2月(5)
- 2016年1月(6)
- 2015年12月(6)
- 2015年11月(9)
- 2015年10月(9)
- 2015年9月(4)
- 2015年8月(3)
- 2015年7月(7)
- 2015年6月(3)
- 2015年5月(6)
- 2015年4月(9)
- 2015年3月(9)
- 2015年2月(6)
- 2015年1月(6)
- 2014年12月(17)
- 2014年11月(8)
- 2014年10月(9)
- 2014年9月(7)
- 2014年8月(12)
- 2014年7月(6)
- 2014年6月(6)
- 2014年5月(9)
- 2014年4月(9)
- 2014年3月(7)
- 2014年2月(3)
- 2014年1月(4)
2019-01-09 17:49
是不是有可能A访问主SPI,B访问从SPI,然后B再请求主的,A再请求从的 两边都没释放,导致的进程僵死了?