您的位置:首页 > 运维架构 > Linux

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

2016-07-11 08:56 633 查看
硬件平台:飞思卡尔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核心层

第二、[b]编写I2C设备驱动[/b]

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_prob
4000
e函数中获取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);

具体代码可见以下地址点击打开链接
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: