利用linux中iic子系统做IIC驱动

利用linuxIIC设备子系统移植IIC设备驱动





  1. 背景描述

IIC总线在嵌入式系统中应用十分广泛,常见的有eepromrtc。一般的处理器会包含IIC的控制器,用来完成IIC时序的控制;另外一方面,由于IIC的时序简单,使用GPIO口来模拟时序也是常见的做法。面对不同的IIC控制器,各种各样的芯片以及linux源码,如何更快做好IIC设备驱动。

  1. 问题描述

在我们的方案中,我们会用到eepromrtc以及tw2865。由于Hi3520IIC控制器设计有问题,无法正常使用。而IIC控制器的SDASCL管脚正好是和两个GPIO管脚复用的。Hisi将控制gpio来实现IIC的时序,从而对IIC设备进行操作。这种设计方式简单明了,但使用IIC子系统,可以更方便的移植和维护其他的设备驱动。

  1. 问题分析

Hisi对于gpio口,rtc芯片以及tw2865的处理方式如下:将gpio口做成一个模块化的驱动,该驱动模拟IIC时序,并向外提供一些函数接口,比如:EXPORT_SYMBOL(gpio_i2c_read_tw2815);等。对于具体的rtc芯片,将其注册为一个misc设备,并利用gpio模块导出的函数进行rtc芯片的配置操作。

其实对于linux-2.6.24\drivers\i2c目录下代码,我们可以加以利用。

LinuxIIC字结构分为三个组成部分:

IIC核心

IIC核心提供了IIC总线驱动和设备驱动的注册、注销方法,IICalgorithm上层的、与具体适配器无关的代码以及探测设备、检测设备地址的上层代码。

IIC总线驱动

IIC总线驱动是对IIC硬件体系结构中适配器端的实现。

IIC设备驱动

IIC设备驱动是对IIC硬件体系总设备端的实现。


我们查看下该目录下的makefilekconfig

obj-$(CONFIG_I2C_BOARDINFO) +=i2c-boardinfo.o

obj-$(CONFIG_I2C) += i2c-core.o

obj-$(CONFIG_I2C_CHARDEV) +=i2c-dev.o

obj-y +=busses/ chips/ algos/

i2c-core.c就是IIC核心,buses中的文件是主流处理器中IIC总线的总线驱动,而chips中的文件就是常用芯片的驱动,algos中的文件实现了一些总线适配器的algorithm,其中就包括我们要用到的i2c-algo-bit.c文件。

我们首先利用i2c-gpio.ci2c-algo-bit.c做好总线驱动。


i2c-gpio.c中,module_initi2c_gpio_initplatform_driver_probe(&i2c_gpio_driver,i2c_gpio_probe);

将其注册为platform虚拟总线的驱动。

staticint __init i2c_gpio_probe(struct platform_device *pdev)中,

定义了如下三个结构体:

structi2c_gpio_platform_data *pdata;//平台相关的gpio的设置

structi2c_algo_bit_data *bit_data;//包含algorithm的具体函数,setor get SDASCL

structi2c_adapter *adap;//适配器

i2c_gpio_probe主要做了下面几件事:

填充bit_data结构的各个函数指针,关联到具体的操作SDASCl函数。

填充adap结构,adap->algo_data= bit_data;

pdata= pdev->dev.platform_data;

bit_data->data= pdata;

pdev->dev->driver_data= adap;

i2c-core中注册适配器类型。

inti2c_bit_add_numbered_bus(struct i2c_adapter *adap)

staticint i2c_bit_prepare_bus(struct i2c_adapter *adap)

adap->algo= &i2c_bit_algo;

i2c_bit_algoadap关联上。

static const structi2c_algorithm i2c_bit_algo = {

.master_xfer = bit_xfer,

.functionality = bit_func,

};

其中,master_xfer函数指针就是IIC传输函数指针。

I2c-algo-bit.c还实现了IIC开始条件,结束条件的模拟,发送字节,接收字节以及应答位的处理。


i2c-gpio.c中的i2c_gpio_setsda_val等函数是与具体平台gpio相关的。

修改对应arch-hi3520v100目录下的gpio.h中的各个函数,这些函数是通过操作寄存器来控制gpio的方向和值。



在对应mach-hi3520v100中的platform-devices.c中添加如下:

static structi2c_gpio_platform_data pdata = {

.sda_pin = 1<<0,

.sda_is_open_drain = 1,

.scl_pin = 1<<1,

.scl_is_open_drain = 1,

.udelay = 4, /* ~100 kHz */

};


static struct platform_devicehisilicon_i2c_gpio_device = {

.name = "i2c-gpio",

.id = -1,

.dev.platform_data = &pdata,

};




static struct platform_device*hisilicon_plat_devs[] __initdata = {


&hisilicon_i2c_gpio_device,

};



int __inithisilicon_register_platform_devices(void)

{

platform_add_devices(hisilicon_plat_devs,ARRAY_SIZE (hisilicon_plat_devs));

return 0;

}

通过platform添加devicesdriver,使得pdev->dev.platform_data=pdata


综合上面的过程,我们完成了adapter的注册,并将用gpio口模拟的algorithmadapter完成了关联。


这样,在rtc-x1205.c中,x1205_attach函数利用i2c核心完成clientadap的关联。

x1205_probe函数中填充i2c_client结构体,并调用i2c_attach_client通知iic核心。

接着注册rtc驱动。


最后我们要读取时间,就需要构造i2c_msg结构体,如下所示:

struct i2c_msg msgs[] = {

{ client->addr, 0, 2,dt_addr }, /* setup read ptr */

{ client->addr, I2C_M_RD,8, buf }, /* read date */

};


/* read date registers */

if((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {

dev_err(&client->dev,"%s: read error\n", __FUNCTION__);

return -EIO;

}

dt_addr是寄存器的地址,I2C_M_RD表示iicread


  1. 经验总结

IIC总线虽然并不复杂,但linux下的IIC子系统却有相当的复杂度。做了很多的抽象工作,代码变得得难理解,但为后续移植驱动工作提供了很多便利条件。在调试gpioadap时,最关键的是对于busdevice driver设备模型的理解。对sysfsproc文件系统很熟悉的话,在调试驱动和后期维护方面大有益处。


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux的I2C子系统是用于在Linux内核管理和操作I2C总线的子系统。它提供了一组API和驱动程序,允许用户空间应用程序与连接到I2C总线上的设备进行通信。 在Linux,I2C子系统由以下几个主要组件组成: 1. I2C核心驱动程序:这是I2C子系统的核心部分,负责管理I2C总线和设备的注册、协议处理等功能。它提供了一组API供其他驱动程序或用户空间应用程序使用。 2. I2C适配器驱动程序:这些驱动程序用于支持特定的硬件I2C适配器,如FPGA、SOC等。它们与I2C核心驱动程序紧密配合,负责将硬件特定的操作转换为通用的I2C操作。 3. I2C设备驱动程序:这些驱动程序用于支持连接到I2C总线上的具体设备。每个I2C设备都有一个对应的设备驱动程序,负责处理设备的初始化、通信协议等。在Linux,这些设备驱动程序通常作为内核模块存在。 4. I2C工具和库:除了内核驱动程序外,Linux还提供了一些用户空间工具和库,用于与I2C设备进行交互。例如,`i2cdetect`工具用于检测I2C总线上的设备地址,`i2cget`和`i2cset`工具用于读取和写入I2C设备的寄存器值。 用户空间应用程序可以使用I2C子系统提供的API和工具来访问和控制连接到I2C总线上的设备。通过打开适当的设备节点文件,并使用相应的读写操作,可以向设备发送命令和数据,以及从设备读取响应和数据。 总而言之,Linux的I2C子系统提供了一套完整的解决方案,使用户能够方便地在Linux环境操作和管理I2C设备。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值