Linux系统I2C设备驱动编写方法

硬件平台:飞思卡尔IMX6

内核版本:kernel3.0.35


Linux的I2C子系统分为三层,I2C核心层,I2C总线驱动层和I2C设备驱动层。I2C核心层由内核开发者提供,I2C总线驱动层有芯片厂商提供,而I2C设备驱动层由于设备的差异性,就只能是具体的开发需求具体实现了。而本实例是拿eeprom芯片AT24C02进行的具体分析。


I2C核心层管理所有关于I2C的数据结构,提供I2C总线驱动层和I2C设备驱动层的操作接口函数,I2C总线驱动层提供I2C核心层访问硬件设备的具体方法,I2C设备驱动层向I2C核心层添加新的数据(总线设备节点)并且提供用户层访问接口。

注意:I2C核心层其实已经提供了用户访问接口函数,每一个I2C总线对应一个设备,/dev/i2c-x(0,1,2...),一般不选择使用,而是自己编写特定的设备驱动


本文档只针对I2C设备驱动的编写方法进行描述,而I2C核心层实现可见driver/i2c/i2c-core.c中有具体实现,I2C总线驱动层具体平台具体分析,比如IMX6平台为drivers\i2c\busses/i2c-imx.c


下面开始正题:I2C设备驱动编写分两部分

第一、在平台文件board-mx6q_sabresd.c中添加i2c_board_info,以及将其注册到I2C核心层

第二、编写I2C设备驱动


1 在平台文件board-mx6q_sabresd.c中添加i2c_board_info,以及将其注册到I2C核心层

步骤:

a、初始化i2c_board_info 类型全局变量

//分配初始化i2c_board_info
static struct i2c_board_info at24c02[] = {
    {
        I2C_BOARD_INFO("at24c02", 0x50) //“at24c02“用来匹配
    }
};

b、在平台设备初始化函数(IMX6平台为mx6_sabresd_board_init)中注册i2c_board_info         

//注册AT24C02的硬件信息
        i2c_register_board_info(0,at24c02, ARRAY_SIZE(at24c02));//参数描述,第一个参数为busnum,第二个参数为struct i2c_board_info const *info,即挂接在总线上的设备集合数组,第三个参数,数组元素个数


2 编写I2C设备驱动

步骤:

a、初始化i2c_driver变量

static struct i2c_device_id at24c02_id[] = {
        {"at24c02", 0}, 
        //”at24c02“必须和i2c_board_info的type一致,匹配靠它进行
};

static struct i2c_driver at24c02_drv = {
    .driver = {
        .name = "tarena" //不重要,匹配不靠它
    },
    .probe = at24c02_probe, //匹配成功执行,i2c-core.c的probe函数会来回调这个函数执行
    .remove = at24c02_remove,
    .id_table = at24c02_id
};

b、注册i2c_driver变量

i2c_add_driver(&at24c02_drv);

c、在at24c02_probe函数中获取i2c_client变量,以及注册混杂设备,以用于后面的数据传输

static struct i2c_client *g_client;

static int at24c02_probe(
            struct i2c_client *client, 
            struct i2c_device_id *id)
{
    //1.注册混杂设备驱动
    misc_register(&at24c02_dev); 
    //2.记录匹配成功的i2c_client
    g_client = client;
    return 0; //成功返回0,失败返回负值
}

d、编写混杂设备操作函数

static struct miscdevice at24c02_dev = {
    .minor = MISC_DYNAMIC_MINOR, //自动分配次设备号
    .name = "at24c02", //dev/at24c02
    .fops = &at24c02_fops
};

static struct file_operations at24c02_fops = {
    .owner = THIS_MODULE,
    .unlocked_ioctl = at24c02_ioctl
};

e、实现at24c02_ioctl函数

ioctl函数实现数据传输接口,这里使用SMBUS接口将数据(地址,数据,设备地址(g_client->addr))丢给I2C总线驱动,启动I2C总线的硬件传输。

具体方法:

(1)打开SMBUS文档:内核源码\Documentation\i2c\smbus-protocol,找到对应的SMBUS接口函数

(2)打开芯片操作时序图,根据时序图找对应的SMBUS操作函数

(3)将addr,data和at24c02_probe函数中匹配成功的i2c_client通过对应的函数丢给I2C总线驱动然后启动I2C总线的硬件传输

比如AT24C02的读写函数分别为

i2c_smbus_read_byte_data(g_client, addr);

i2c_smbus_write_byte_data(g_client, addr, data);


具体代码可见以下地址点击打开链接









  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值