I2C(Inter-Integrated Circuit)总线是一种由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备。I2C总线产生于在80年代,最初为音频和视频设备开发,如今主要在服务器管理中使用,其中包括单个组件状态的通信。例如管理员可对各个组件进行查询,以管理系统的配置或掌握组件的功能状态,如电源和系统风扇。可随时监控内存、硬盘、网络、系统温度等多个参数,增加了系统的安全性,方便了管理。
(1)主控在检测到总线空闲的状况下,首先发送一个START信号掌管总线;
(2)发送一个地址字节(包括7位地址码和一位R/W);
(3)当被控器件检测到主控发送的地址与自己的地址相同时发送一个应答信号(ACK);
(4)主控收到ACK后开始发送第一个数据字节;
(5)被控器收到数据字节后发送一个ACK表示继续传送数据,发送NACK表示传送数据结束;
(6)主控发送完全部数据后,发送一个停止位STOP,结束整个通讯并且释放总线;
(1)主控在检测到总线空闲的状况下,首先发送一个START信号掌管总线;
(2)发送一个地址字节(包括7位地址码和一位R/W);
(3)当被控器件检测到主控发送的地址与自己的地址相同时发送一个应答信号(ACK);
(4) 主控收到ACK后释放数据总线,开始接收第一个数据字节;
(5)主控收到数据后发送ACK表示继续传送数据,发送NACK表示传送数据结束;
(6)主控发送完全部数据后,发送一个停止位STOP,结束整个通讯并且释放总线;
SDA和SCL两条信号线都处于高电平,即总线上所有的器件都释放总线,两条信号线各自的上拉电阻把电平拉高;
时钟信号SCL保持高电平,数据信号SDA的电平被拉低(即负跳变)。启动信号必须是跳变信号,而且在建立该信号前必修保证总线处于空闲状态;
时钟信号SCL保持高电平,数据线被释放,使得SDA返回高电平(即正跳变),停止信号也必须是跳变信号。
SCL线呈现高电平期间,SDA线上的电平必须保持稳定,低电平表示0(此时的线电压为地电压),高电平表示1(此时的电压由元器件的VDD决定)。只有在SCL线为低电平期间,SDA上的电平允许变化。
I2C总线的数据都是以字节(8位)的方式传送的,发送器件每发送一个字节之后,在时钟的第9个脉冲期间释放数据总线,由接收器发送一个ACK(把数据总线的电平拉低)来表示数据成功接收.
在时钟的第9个脉冲期间发送器释放数据总线,接收器不拉低数据总线表示一个NACK,NACK有两种用途:
a. 一般表示接收器未成功接收数据字节;
b. 当接收器是主控器时,它收到最后一个字节后,应发送一个NACK信号,以通知被控发送器结束数据发送,并释放总线,以便主控接收器发送一个停止信号STOP。
地址的分配方法有两种:
1. 含CPU的智能器件,地址由软件初始化时定义,但不能与其它的器件有冲突;
2. 不含CPU的非智能器件,由厂家在器件内部固化,不可改变。
高7位为地址码,其分为两部分:
1. 固定部分,不可改变,由厂家固化的统一地址;
2. 可编程部分,此部分由器件可使用的管脚决定。例如,如果器件有4个固定的和3个可编程的地址位,那么相同的总线上共可以连接8个相同的器件(并非所有器件都可以设定)。
注册过程:
drivers/i2c/busses/i2c-qup.c(这是适配器的驱动) platform_driver_register qup_i2c_probe //在arch/arm/mach-msm/devices-msm8x60.c中定义了多少个gsbix_qup_i2c_resources就有多少个I2C Adapter,这个probe函数就会执行多少次 i2c_add_numbered_adapter i2c_register_adapter i2c_scan_static_board_info i2c_new_device //arch/arm/mach-msm/board-xxx.c里面定义的i2c设备在此注册(这就是静态注册) device_register //从这句开始即是设备模型的东西 device_add bus_probe_device device_attach __device_attach //每注册一个设备都会调用此函数,每注册一个驱动也会调用__driver_attach,先注册设备还是驱动无硬性规定,不过驱动和设备是相偎相依的 driver_match_device //会根据device的name字段和bus上挂载的drivers链表中每一个driver的id_table的name字段比较,如果相等即找到了自己的driver driver_probe_device //如果相等调用此函数,不相等返回0。接下来会调用具体设备驱动的probe函数 drivers/i2c/i2c-dev.c 调用到的__process_new_driver-->i2c_do_add_adapter-->attach_adapter会真正执行,其他地方调用此函数均不执行。每一个i2c adapter会在/dev下生成一个字符设备。
这里只写了大概的流程,有兴趣的读者可自行跟踪代码流程。
gsbi是物理上实际存在的部件,它可以模拟成i2c、gpio、spi、uart、sdio等,此i2c即是gsbi模拟的。这里顺便提下i2c adapter和i2c总线,两者都是物理上必须存在的,哪怕是其他部件模拟的,例如GSBI模拟I2C,那么GSBI这个部件是实际存在的。GSBI的走线会与所有i2c设备互连,GSBI的接口即是i2c adapter,与其他i2c设备互连的走线即是i2c总线。如果GSBI模拟成uart,那么与uart的rx/tx pin连接的走线即是uart串口线。这是高通平台的设计,换作其他平台,也一定会有一个i2c adapter或者说可以模拟成i2c adapter的物理部件存在。猜测i2c adapter位于片上系统中,类似I/O接口的东西,没有固件,驱动它的代码即是各平台相关的i2c adapter driver。GSBI的地址以及模拟成的qup i2c/uart的地址都是编址好的,在arch/arm/mach-msm/devices-msm8x60.c最开头可以看到这些物理地址。我们知道ARM是统一编址的,在代码中要用ioremap把它映射到虚拟内存,这样就可以访问了。
原文:https://www.cnblogs.com/yuanqiangfei/p/14915344.html