i2c学习笔记

本文将从以下三个方面进行:

  1. 概述i2c协议;
  2. linux i2c的软件框架与核心实现;
  3. 怎样编写i2c驱动;
  4. 用户态编程使用i2c驱动。

概述

I2C协议是嵌入式系统中广泛使用的一类通信协议,主要用于CPU和各种外设之间的低速数据通信。Linux kernel使用I2C framework抽象、管理相应的资源,并以各种形式,向各类使用者提供API。作为总线(bus)的一种,I2C framework的实现体现了linux设备模型的精髓,值得研究与学习。
I2C是一个能够支持多个设备的总线,包含一条双向串行数据线SDA,一条串行时钟线SCL。i2c支持三种速率模式, 普通模式:100kHz;快速模式:400kHz;高速模式:3.4MHz。
i2c学习笔记

i2c协议

  1. 空闲状态
    i2c总线总线的SDA和SCL两条信号线同时处于高电平时,规定为总线的空闲状态。此时各个器件的输出级场效应管均处在截止状态,即释放总线,由两条信号线各自的上拉电阻把电平拉高。

  2. 起始位与停止位的定义
    起始信号:当SCL为高期间,SDA由高到低的跳变;启动信号是一种电平跳变时序信号,而不是一个电平信号。
    停止信号:当SCL为高期间,SDA由低到高的跳变;停止信号也是一种电平跳变时序信号,而不是一个电平信号。
    i2c学习笔记

  3. 数据发送与应答
    在起始信号后,发送端发送8bit数据,接收端在第9个时钟发送ACK应答信号。
    i2c学习笔记
    在SCL低电平时,SDA上的电平进行改变;在SCL高电平时,SDA上的电平状态必须保持稳定,接收端在SCL高电平时读取数据。

  4. i2c读写时序

  • i2c写数据时序
    在起始信号后,主机发送一个7bit的从机地址和一个读写位(0:写,1:读),对应地址的从机发送一个ACK,主机开始写入8bit数据,从机ACK,结束信号。
    i2c学习笔记
  • i2c读数据时序
    在起始信号后,主机发送一个7bit的从机地址和一个读写位(0:写,1:读),对应地址的从机发送一个ACK,从机发送8bit数据,主机发送ACK,结束信号。
    i2c学习笔记

RTC-RX8010协议

rx8010指定寄存器写入时序:

  1. 主机发送起始信号
  2. 主机发送从机rx8010地址和读标志位
  3. rx8010发送ACK
  4. 主机发送欲写入的寄存器地址
  5. rx8010发送ACK
  6. 主机发送写入数据
  7. rx8010发送ACK
  8. [可选]继续写入数据可重复6、7步骤,寄存器地址会自动增加
  9. 主机发送停止信号

i2c学习笔记
i2c学习笔记

rx8010指定寄存器读取时序:

  1. 主机发送起始信号
  2. 主机发送从机rx8010地址和写标志位
  3. rx8010发送ACK
  4. 主机发送欲读取的寄存器地址
  5. rx8010发送ACK
  6. 主机发送起始信号(restart)
  7. 主机发送从机rx8010地址和读标志位
  8. rx8010发送寄存器数据
  9. 主机发送ACK则rx8010继续发送数据(寄存器自动增加),主机发送NACK则rx8010停止发送数据
  10. 主机发送停止信号
    i2c学习笔记

linux i2c驱动框架分析

linux i2c驱动的三个核心文件:
设备驱动:i2c-dev.c
提供用户接口(read、write等);
实现策略:知道发什么数据,但是不知道怎么发。
核心驱动:i2c-core.c

注册i2c总线;
给驱动编写提供接口。
总线驱动:i2c-xxx.c (xxx为对应的plat)

初始化硬件(i2c控制器);
实现操作方法:知道怎么发数据,不知道发什么数据。
i2c学习笔记

i2c子系统开发-设备驱动设计的重要函数(linux/i2c.h)

数据接收与发送

int i2c_master_send(const struct i2c_client *client, const char *buf, int count);

int i2c_master_recv(const struct i2c_client *client, char *buf, int count);

int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num);

int i2c_register_board_info(int busnum, struct i2c_board_info const *info, unsigned n);

适配器增加与删除

int i2c_add_adapter(struct i2c_adapter *);
void i2c_del_adapter(struct i2c_adapter *);
int i2c_add_numbered_adapter(struct i2c_adapter *);

驱动注册与删除

int i2c_register_driver(struct module *, struct i2c_driver *);
void i2c_del_driver(struct i2c_driver *);

设备增加与注销

i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info);

void i2c_unregister_device(struct i2c_client *);

i2c学习笔记

i2c总线驱动层