I2C协议及其源码跟进
(一)I2C协议简介
I2C协议特点:
I2C总线示意图
1.它是飞利浦公司生产的一种串口协议;
2.它是两根线传输的 SDA,SCl 数据时钟线;
3.两根线上必须要由上拉电阻;(上拉电阻的作用是将不确定的信号通过一个电阻与电源相连,固定在高电平,同时起到限流的作用。)
4.可以挂多个设备,采用的是主从模式;
5. I2C的时钟都是由主机产生的;
6.半双工通信方式 (SPI 全双工的,四根线,串行的);
7.速度问题,低速模式:100K/s 全速模式:400k/s 高速模式:3.4M/s (SPI 的速度一般在 10M 左右);
8.真正的多主机总线;
9. 串行 8 位双向传输,先传高位再传低位 ;
I2C时序图规定:
I2C一般是有7位/10位寻址的;
①I2C起始和停止信号
起始信号:在SCL线是高电平时 SDA 线从高电平向低电平切换;
停止信号:当SCL线是高电平时 SDA 线由低电平向高电平切换。
②数据的有效性
在SCL线为高电平时,SDA 线上的数据保持稳定,也就是说SDA线的高低改变只能是在SCL线为低时,当然起停信号不在此列。
③响应问题
第九个电平的低电平期间,主机会将SDA线拉低,第九个高电平期间,从机将SDA线拉低,同时主机将检测SDA是为0还是为1,为零表示有响应,否则无响应。
I2C发送数据,读写操作
“0”为写,“1”为读,写操作是直接先写地址再写数据,读操作是先写地址再改为读,再读取数据。
(二)I2C层次架构
了解完了I2C协议的一些规定及特点之后,然后进入Linux内核源码(Linux-2.6.22.6)跟进阶段。我们知道I2C驱动总共分为三层,I2C总线适配器驱动层,设备驱动层,I2C核心层。I2C框架关系图如下:
总线适配器驱动层是一个平台设备驱动(platform-device-driver),对应的是控制器的驱动,它分为I2C控制器驱动(i2c-s3c2410.c文件中)和设备资源(在devs.c文件中声明资源,在mach-smdk2410.c中注册资源),对应一个虚拟总线将它们挂接起来,定义描述具体i2c总线适配器的i2c_adapter数据结构、实现在具体i2c适配器上的i2c总线通信方法,并由i2c_algorithm数据结构进行描述。
设备驱动层是对于具体设备的一个驱动比如eeprom驱动(在eeprom.c文件中),由I2C总线将驱动与控制器挂接起来;定义描述具体设备的i2c_client和可能的私有数据结构、借助i2c框架的i2c_probe函数实现注册设备的attach_adapter方法、提供设备可能使用的地址范围、以及设备地址检测成功后创建i2c_client数据结构的回调函数。
I2C核心层(在i2c-core.c和i2c.h中)就类似于一个封装起来的函数库,它提供公用的结构体,提供注册和注销的接口,提供公用或者转接函数,起一个上下层承接的作用。
还有一个分离出来东西i2c-dev.c文件,i2c-dev模块为系统中所有的i2c适配器创建相应的/dev/i2c/%d字符设备节点,并注册设备访问方法,从而使得用户进程可以访问该i2c总线上的设备。它包含对I2C适配器申请主设备号(内核中已规定#define I2C_MAJOR 89)和创建设备类以及对设备的操作方法file_operations(也就是找到对应的adapter和client并作相应操作),主设备号的申请放这里是因为可以有多条I2C总线所以以主次设备号表示,而不是有一个申请一个,浪费系统资源。