linuxi2c命令 linux i2c编程

用linux 调用内核中的统一I2C驱动 i2c总是 busy,求大神支招,谢谢! 程序很短最近我也遇到这个问题了,纠结了一天,在网友的支持下解决了,这个天嵌的版本中,i2c和他的摄像头驱动(OV9650驱动)相冲突,你在编译内核之前,将摄像头的驱动全部去掉,这样子重新编译之后 , i2c就可以正常测试使用了 。
在linux上怎样增加一个i2c设备?假设手上有一块从淘宝上买来的开发板linuxi2c命令,linuxi2c命令我要在开发板的I2C总线上增加一个从设备(如at24c08)linuxi2c命令,那么我要怎样写这个“I2C设备驱动”linuxi2c命令,让
应用程序可以访问at24c08呢?
先来看一个最简单的i2c设备驱动:
static struct i2c_board_info at24cxx_info = { //所支持的i2c设备的列表
I2C_BOARD_INFO("at24c08", 0x50),//一项代表一个支持的设备linuxi2c命令,它的名字叫做“at24c08”,器件地址是0x50
};
static struct i2c_client *at24cxx_client;
static int at24cxx_dev_init(void)
{
struct i2c_adapter *i2c_adap;//分配一个适配器的指针
i2c_adap = i2c_get_adapter(0);//调用core层的函数 , 获得一个i2c总线 。这里我们已经知道新增的器件挂接在编号为0的i2c总线上
at24cxx_client = i2c_new_device(i2c_adap, at24cxx_info);// 把i2c适配器和新增的I2C器件关联起来,这个用了i2c总线0,地址是0x50 。这就组成了一个客户端
at24cxx_client i2c_put_adapter(i2c_adap);
return 0;
}
static void at24cxx_dev_exit(void)
{
i2c_unregister_device(at24cxx_client);
}
module_init(at24cxx_dev_init);
module_exit(at24cxx_dev_exit);
从上面的程序可以看到 , 写一个i2c设备驱动程序,与写普通的字符驱动基本一样 。特别之处是它调用了i2c的core层的函数,以获得对i2c总线的控制 。因为用的是开发板,板上的与soc芯片(一般来说就是arm的芯片)i2c总线驱动一般都做好了 , 直接调用core层的函数就可以控制soc的i2c模块了 。也就是说,写i2c设备驱动不需要关注arm内部的i2c模块的寄存器,我们需要关注的是设备(at24c08)的寄存器以及它的datasheet对时序的要求 。
其实,添加i2c设备的方法很灵活 。根据Linux的官方文档《linux-3.4.2\Documentation\i2c\instantiating-devices》,添加i2c设备的方法总结有4种:
1. i2c_register_board_info:根据总线编号、设备名字(“at24c08”)、设备地址(0x50)注册一个字符驱动 。这种方法最简单、最粗暴 , 最贴近平时在开片机上开发i2c器件的 。
2. i2c_new_device:根据i2c总线的编号,声明一个i2c设备:这种方法就是上面例子用的方法 。这种方法也简单,但是需要事先知道器件挂接在哪条总线上 。对于设备 , 还实现知道了设备地址0x50,总线适配器也支持名字为“at24c08”的设备
3. i2c_new_probed_device:
4.从用户空间实例化一个器件:这个方法相当智能快速,如下输入指令 , 即可增加一个i2c设备,同时增加了对应的设备文件 。
# echo eeprom 0x50/sys/bus/i2c/devices/i2c-3/new_device
根据英文文档的标题,添加i2c设备有称之为“i2c设备的实例化” 。
从上述可以知道,在实例化一个i2c设备之前,除了有对应的驱动支持总线外(这里是总线0),还需要有一个驱动使用了总线0发送时序,支持名字为"at24c08"的器件 。这个驱动用总线驱动的函数,配置了at24c08的寄存器 。
linux下怎么直接使用iic接口利用Linux中IIC设备子系统移植IIC设备驱动
背景描述
IIC总线在嵌入式系统中应用十分广泛,常见的有eeprom,rtc 。一般的处理器会包含IIC的控制器,用来完成IIC时序的控制;另外一方面 , 由于IIC的时序简单,使用GPIO口来模拟时序也是常见的做法 。面对不同的IIC控制器,各种各样的芯片以及linux源码,如何更快做好IIC设备驱动 。
问题描述
在我们的方案中,我们会用到eeprom,rtc以及tw2865 。由于Hi3520的IIC控制器设计有问题,无法正常使用 。而IIC控制器的SDA和SCL管脚正好是和两个GPIO管脚复用的 。Hisi将控制gpio来实现IIC的时序,从而对IIC设备进行操作 。这种设计方式简单明了,但使用IIC子系统 , 可以更方便的移植和维护其他的设备驱动 。
问题分析
Hisi对于gpio口,rtc芯片以及tw2865的处理方式如下:将gpio口做成一个模块化的驱动,该驱动模拟IIC时序,并向外提供一些函数接口,比如:EXPORT_SYMBOL(gpio_i2c_read_tw2815);等 。对于具体的rtc芯片,将其注册为一个misc设备 , 并利用gpio模块导出的函数进行rtc芯片的配置操作 。
其实对于linux-2.6.24\drivers\i2c目录下代码,我们可以加以利用 。
Linux的IIC字结构分为三个组成部分:
IIC核心
IIC核心提供了IIC总线驱动和设备驱动的注册、注销方法 , IICalgorithm上层的、与具体适配器无关的代码以及探测设备、检测设备地址的上层代码 。
IIC总线驱动
IIC总线驱动是对IIC硬件体系结构中适配器端的实现 。
IIC设备驱动
IIC设备驱动是对IIC硬件体系总设备端的实现 。
我们查看下该目录下的makefile和kconfig:
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.c和i2c-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 SDA和SCL
structi2c_adapter *adap;//适配器
i2c_gpio_probe主要做了下面几件事:
填充bit_data结构的各个函数指针 , 关联到具体的操作SDA和SCl函数 。
填充adap结构,adap-algo_data= https://www.04ip.com/post/bit_data;
pdata= https://www.04ip.com/post/pdev-dev.platform_data;
bit_data-data= https://www.04ip.com/post/pdata;
pdev-dev-driver_data= https://www.04ip.com/post/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_algo与adap关联上 。
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 = https://www.04ip.com/post/{
.sda_pin = 10,
.sda_is_open_drain = 1,
.scl_pin = 11,
.scl_is_open_drain = 1,
.udelay = 4, /* ~100 kHz */
};
static struct platform_devicehisilicon_i2c_gpio_device = {
.name = "i2c-gpio",
.id = -1,
.dev.platform_data = https://www.04ip.com/post/pdata,
};
static struct platform_device*hisilicon_plat_devs[] __initdata = https://www.04ip.com/post/{
hisilicon_i2c_gpio_device,
};
int __inithisilicon_register_platform_devices(void)
{
platform_add_devices(hisilicon_plat_devs,ARRAY_SIZE (hisilicon_plat_devs));
return 0;
}
通过platform添加devices和driver,使得pdev-dev.platform_data=https://www.04ip.com/post/pdata
综合上面的过程,我们完成了adapter的注册 , 并将用gpio口模拟的algorithm与adapter完成了关联 。
这样,在rtc-x1205.c中,x1205_attach函数利用i2c核心完成client和adap的关联 。
在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 。
求教高手,在linux内核中怎么修改i2c的通信速率为400KHz1、先查看I2C设备速率 。
sudo cat /sys/module/i2c_bcm2708/parameters/baudrate
默认的I2C速度为100KHz,对于多数I2C设备而言100KHz并不算快 。
2、修改I2C通信速率 。进入/etc/modprobe.d目录,并在该目录下新建一个costom.conf文件,在该文件中插入options i2c_bcm2708 baudrate=400000,400000便为新的I2C速率400KHz,最后请重启系统 。
cd/etc/modprobe.d#进入/etc/modprobe.d 目录
sudo nano custom.conf#在该目录新建一个名为custom.conf文件 , 并插入以下内容
#options i2c_bcm2708 baudrate=400000
sudo reboot#重启系统
【linuxi2c命令 linux i2c编程】linuxi2c命令的介绍就聊到这里吧,感谢你花时间阅读本站内容 , 更多关于linux i2c编程、linuxi2c命令的信息别忘了在本站进行查找喔 。

    推荐阅读