linux i2c驱动
Linux下I2C驱动介绍
1、I2C概述I2C是philips公司提供的外设总线,I2C有两条数据线,一条是串行数据线SDA、一条是时钟线SCL,使用SDA和SCL实现了数据的交换,便于布线。
I2C总线方便用在EEPROM、实时钟、小型LCD等与CPU外部的接口上。
2、Linux下的驱动思路Linux系统下编写I2c驱动主要有两种方法:一种是把I2C当做普通字符设备来使用;另一种利用Linux下驱动的体系结构来实现。
第一种方法:优点:思路比较直接,不用花费大量时间去了解Linux系统下I2C体系结构缺点:不仅对I2C设备操作要了解,还有了解I2C的适配器操作不仅对I2C设备器和设备操作需要了解,编写的驱动移植性差,内核提供的I2C设备器都没有用上。
第二种方法:第一种的优点就是第二种的缺点,第一种的缺点就是第二种的优点。
3、I2C框架概述Linux的I2C体系结构分为3部分:1)I2C核心I2C核心提供了I2C总线驱动和设备驱动的注册和注销的方法,I2C 通信方法(algorithm)上层,与具体适配器无关的代码,检测设备上层的代码等。
2)I2C总线驱动I2C总线驱动是对I2C硬件体系结构中适配器端的实现,适配器可以直接受CPU来控制。
3)I2C设备驱动I2C设备驱动是对I2C硬件体系结构中设备端的实现,设备端挂在受CPU控制的适配器上,通过I2C适配器与CPU交换数据。
Linux下的I2C体系结构:1)Linux下的I2C体系结构4、I2C设备驱动编写方法首先让我们明白适配器驱动的作用是让我们能够通过它发出标准的I2C时序,在linux内核源代码中driver/I2C/buss包含一些适配器的驱动,例如s3c2410的驱动I2C-s3c2410.c,适配器被加载到内核中,接下的任务就是实现设备驱动的编写。
编写设备驱动的方法主要分为两种方法:第一种:利用设备提供的I2C-dev.c来实现I2C适配器设备文件,然后通过上层应用程序来操作I2C设备器来控制I2C设备。
嵌入式Linux中I2C设备驱动程序的研究与实现
嵌入式Linux中I2C设备驱动程序的研究与实现
朱南皓;李正祥
【期刊名称】《微计算机信息》
【年(卷),期】2010(026)011
【摘要】FC作为一种目前通用的总线技术,已广泛应用于EEPROM、实时钟、小型LCD等设备与CPU的接口中.分析了嵌入式Linux中I2C驱动程序的体系结构,I2C驱动程序中一些重要数据结构之间的关系以及I2C驱动程序的运行机制.最后,结合具体的EEPROM芯片AT24C08说明了在嵌入式Linux下开发I2C设备驱动程序的一般流程.另外还创新了一般的驱动方法,实现了单设备多驱动的驱动模式.【总页数】3页(P67-69)
【作者】朱南皓;李正祥
【作者单位】100024,北京,中国传媒大学广播电视数字化教育部工程研究中心;100024,北京,中国传媒大学广播电视数字化教育部工程研究中心
【正文语种】中文
【中图分类】TP316
【相关文献】
1.小型医疗仪器中嵌入式Linux设备驱动程序的开发 [J], 甄诚;董秀珍;付峰;刘晓东
2.设备驱动程序在嵌入式Linux系统中的实现分析 [J], 王莹
3.嵌入式Linux的I2C设备驱动程序的分析 [J], 余炽业;宋跃;雷瑞庭
4.嵌入式Linux系统中字符设备驱动程序的开发 [J], 李胜朝;黄先祥;谢建
5.设备驱动程序在嵌入式Linux系统中的实现分析 [J], 王莹
因版权原因,仅展示原文概要,查看原文内容请购买。
i2c_rtc_rx8025驱动总结
ARM : at91-sam9x5ekLinux内核:linux-2.6.39时钟芯片:rx8025 SA/NB第一种方法:Rx8025驱动程序在该linux内核中已经包含,路径为:drivers/rtc/rtc-rx8025.c所以在内核中增加驱动只需要配置即可:1.执行make ARCH=arm menuconfig 进入菜单选项,选择RTC配置,选中EPSONRX-8025SA/NB,同时一定要去掉cpu自带的时钟。
2.i2c support 需要选中I2C Hardware Bus support中GPIO-based bitbanging I2C,否则,即使rtc驱动正确,也不能使用,提示:drivers/rtc/hctosys.c: unable to open rtc device (rtc0)。
问题源自,驱动配置正确,I2C驱动没有加载正确,udevd不能创建rtc0设备节点3.在arch/arm/mach-at91/board-sam9x5ek.c中添加信息,注意此处的name名称要与驱动程序中id_table中的名称保持一致。
而在linux某些匹配机制中,设备名称是与驱动名称相一致。
如果名称不能正确匹配,系统是不会执行probe函数的。
另外需要注意的是i2c地址,手册上给出的地址一般都是带有读写位的,而程序中的地址需要把最后一位的读写位去掉,取前面的7位。
Rx8025的地址为0x64,相应的程序中的地址应该为0x32。
否则会提示对寄存器的操作失败。
4.驱动正确配置后,生成相应的文件/dev/i2c-0/dev/rtc0/sys/bus/i2c/drivers/rtc-rx8025/sys/bus/i2c/drivers/0-0032。
linux下iic(i2c)读写AT24C02
/jammy_lee/linux下iic(i2c)读写AT24C02linux驱动2010-02-09 16:02:03 阅读955 评论3 字号:大中小订阅linux内核上已有iic的驱动,因此只需要对该iic设备文件进行读写则能够控制外围的iic器件。
这里以AT24C02为对象,编写一个简单的读写应用程序。
iic设备文件在我的开发板上/dev/i2c/0 ,打开文件为可读写。
AT24C02的器件地址为0x50 ,既是iic总线上从器件的地址,每次只读写一字节数据。
/************************************************************///文件名:app_at24c02.c//功能:测试linux下iic读写at24c02程序//使用说明: (1)// (2)// (3)// (4)//作者:jammy-lee//日期:2010-02-08/************************************************************///包含头文件#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/ioctl.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/select.h>#include <sys/time.h>#include <errno.h>//宏定义#define Address 0x50 //at24c02地址#define I2C_RETRIES 0x0701#define I2C_TIMEOUT 0x0702#define I2C_SLAVE 0x0703 //IIC从器件的地址设置#define I2C_BUS_MODE 0x0780typedef unsigned char uint8;uint8 rbuf[8] = {0x00}; //读出缓存uint8 wbuf[8] = {0x01,0x05,0x06,0x04,0x01,0x01,0x03,0x0d}; //写入缓存int fd = -1;//函数声明static uint8 AT24C02_Init(void);static uint8 i2c_write(int fd, uint8 reg, uint8 val);static uint8 i2c_read(int fd, uint8 reg, uint8 *val);static uint8 printarray(uint8 Array[], uint8 Num);//at24c02初始化static uint8 AT24C02_Init(void){fd = open("/dev/i2c/0", O_RDWR); //允许读写if(fd < 0){perror("Can't open /dev/nrf24l01 \n"); //打开iic设备文件失败exit(1);}printf("open /dev/i2c/0 success !\n"); //打开iic设备文件成功if(ioctl(fd, I2C_SLAVE, Address)<0) { //设置iic从器件地址printf("fail to set i2c device slave address!\n");close(fd);return -1;}printf("set slave address to 0x%x success!\n", Address);if(ioctl(fd, I2C_BUS_MODE, 1)<0) //设置iic总线模式printf("set bus mode fail!\n");elseprintf("set bus mode ok!\n");return(1);}/*uint8 AT24C02_Write(uint8 *nData, uint8 Reg, uint8 Num){write(fd, &Reg, 1); //usleep(100); //延时100uswrite(fd, nData, Num);usleep(1000*4); //延时4msreturn(1);}uint8 AT24C02_Read(uint8 nData[], uint8 Reg, uint8 Num) {write(fd, &Reg, 1);usleep(100); //延时100usread(fd, nData, Num);usleep(1000*4); //延时4msreturn(1);}*///at24c02写入一字节static uint8 i2c_write(int fd, uint8 reg, uint8 val){int retries;uint8 data[2];data[0] = reg;data[1] = val;for(retries=5; retries; retries--) {if(write(fd, data, 2)==2)return 0;usleep(1000*10);}return -1;}//at24c02读取一字节static uint8 i2c_read(int fd, uint8 reg, uint8 *val){int retries;for(retries=5; retries; retries--)if(write(fd, ®, 1)==1)if(read(fd, val, 1)==1)return 0;return -1;}//输出数组static uint8 printarray(uint8 Array[], uint8 Num) {uint8 i;for(i=0;i<Num;i++){printf("Data [%d] is %d \n", i ,Array[i]);}return(1);}//主函数int main(int argc, char *argv[]){int i;AT24C02_Init();usleep(1000*100);for(i=0; i<sizeof(rbuf); i++)if(i2c_read(fd, i, &rbuf[i]))break;printarray(rbuf ,8);printf("Before Write Data \n"); sleep(1);for(i=0; i<sizeof(rbuf); i++)if(i2c_write(fd, i, wbuf[i]))break;printarray(wbuf ,8);printf("Writing Data \n");sleep(1);for(i=0; i<sizeof(rbuf); i++)if(i2c_read(fd, i, &rbuf[i]))break;printarray(rbuf ,8);printf("After Write Data \n");close(fd);}。
Linux下基于I2C的电源管理芯片驱动设计
0 引 言
内部 集 成 电路 (ne—ne rtd crut 2 itritg ae i i c ,IC)
12 IC 总 线 信 号 时序 . 2
S DA 和 S L2条 信 号 线 都 处 于 高 电平 ,即 总 线 C 空 闲状 态 , 2条 信 号 线 各 自的 上 拉 电阻 把 电平 拉 高 ;
( tritgae i ut u d r iu . h 2 u miga dtese il rhtcueo eICb s nte n xk re ae i e— e rtdcr i n e n x T eICb s i n n p ca ac i tr fh 2 u u en l r n n c ) L t h e t i h Li
23 I C设 备 驱 动 . 2
CON Dn1 oN
图 1 IC总 线起 始 信 号 与结 束信 号【 2
定 义 描 述 具 体 设 备 的 IC cin 2 l t和 可 能 的私 有 e 数 据 结 构 、借 助 IC 框 架 的 IC pr be 函 数 实 现 注 2 2 o
S
‘ 、
.
源 转 换 输 出 的应 用 ,提 供 简 单 易 用 而 又 可 以灵 活 配 置 的完 整 电源 解 决 方 案 , 充 分 满 足 目前 日益 复 杂 的 应 用 处 理器 系 统 对 于 电源 相 对 复 杂 而 精 确 控 制 的要 求 。AXP 9 提 供 了一 个 与主 机 通 讯 的 两 线 串行 通 12
接 收 端 接 收 完 一 个 字 节 后 , 会 立 刻 在 AC 周 期 内 K
1 IC总线 概 述 与时序 2
11 IC 总 线 介 绍 . 2
将 S DA 由高 电平 翻 转 为低 电 平 ,这 便 产 生 了 一 个
i2c驱动传入probe的参数解释
I2C驱动传入probe的参数解释在进行I2C设备的驱动开发过程中,常常会涉及到I2C驱动的probe 函数。
probe函数是Linux内核驱动中的一种特殊函数,它在驱动被加载并且设备被检测到时被调用,用于初始化设备并注册设备驱动。
在编写I2C驱动的probe函数时,通常需要传入不同的参数进行配置和初始化。
本文将对I2C驱动传入probe的参数进行解释和说明,帮助读者更好地理解和使用I2C设备驱动。
1. struct i2c_client *client在I2C驱动的probe函数中,通常需要传入一个指向structi2c_client结构体的指针作为参数。
这个结构体是I2C设备在内核中的表示,包含了I2C设备的位置区域、总线信息、驱动信息等。
通过这个参数,我们可以获取I2C设备的各种信息,并进行相应的初始化和配置。
2. const struct i2c_device_id *id另一个常见的参数是一个指向const struct i2c_device_id结构体的指针,用于指定要注册的设备驱动的ID信息。
这个结构体中通常包含了设备的厂商ID、设备类型、设备名称等信息,用于匹配加载指定的设备驱动。
在probe函数中,我们可以使用这个参数来判断当前检测到的I2C设备是否匹配当前的驱动,从而进行相应的初始化和注册操作。
3. int (*probe)(struct i2c_client *client, const struct i2c_device_id *id)最后一个重要的参数是probe函数本身。
这个参数是一个函数指针,用于指定实际的probe函数的位置区域。
在probe函数中,我们可以根据传入的client和id参数,进行设备的初始化、资源的申请、注册设备驱动等操作。
通过这个函数指针参数,内核可以在加载驱动并检测到设备时正确地调用对应的probe函数。
I2C驱动传入probe的参数包括指向I2C设备结构体的指针、指向设备ID信息的指针以及probe函数的函数指针。
I2C实例解析
实例解析linux内核I2C体系结构(1)一、概述谈到在linux系统下编写I2C驱动,目前主要有两种方式,一种是把I2C设备当作一个普通的字符设备来处理,另一种是利用linux I2C驱动体系结构来完成。
下面比较下这两种驱动。
第一种方法的好处(对应第二种方法的劣势)有:●思路比较直接,不需要花时间去了解linux内核中复杂的I2C子系统的操作方法。
第一种方法问题(对应第二种方法的好处)有:●要求工程师不仅要对I2C设备的操作熟悉,而且要熟悉I2C的适配器操作;●要求工程师对I2C的设备器及I2C的设备操作方法都比较熟悉,最重要的是写出的程序可移植性差;●对内核的资源无法直接使用。
因为内核提供的所有I2C设备器及设备驱动都是基于I2C子系统的格式。
I2C适配器的操作简单还好,如果遇到复杂的I2C适配器(如:基于PCI的I2C适配器),工作量就会大很多。
本文针对的对象是熟悉I2C协议,并且想使用linux内核子系统的开发人员。
网络和一些书籍上有介绍I2C子系统的源码结构。
但发现很多开发人员看了这些文章后,还是不清楚自己究竟该做些什么。
究其原因还是没弄清楚I2C子系统为我们做了些什么,以及我们怎样利用I2C子系统。
本文首先要解决是如何利用现有内核支持的I2C适配器,完成对I2C设备的操作,然后再过度到适配器代码的编写。
本文主要从解决问题的角度去写,不会涉及特别详细的代码跟踪。
二、I2C设备驱动程序编写首先要明确适配器驱动的作用是让我们能够通过它发出符合I2C标准协议的时序。
在Linux内核源代码中的drivers/i2c/busses目录下包含着一些适配器的驱动。
如S3C2410的驱动i2c-s3c2410.c。
当适配器加载到内核后,接下来的工作就要针对具体的设备编写设备驱动了。
编写I2C设备驱动也有两种方法。
一种是利用系统给我们提供的i2c-dev.c来实现一个i2c 适配器的设备文件。
然后通过在应用层操作i2c适配器来控制i2c设备。
i2c_register_driver函数详解
i2c_register_driver函数详解在嵌入式软件开发中,I2C(Inter-Integrated Circuit)总线是一种常用的串行通信接口,用于在微控制器和外部设备之间传输数据。
i2c_register_driver函数是Linux内核中一个重要的函数,用于注册I2C 驱动程序。
本文将详细解析i2c_register_driver函数的功能、参数和应用。
一、i2c_register_driver函数概述i2c_register_driver函数是在Linux内核中注册一个I2C驱动程序的函数。
它的作用是将驱动程序与对应的I2C适配器绑定,使得操作系统能够正确地识别和管理该驱动程序。
在驱动程序注册后,当相应的I2C设备连接到系统时,驱动程序将会自动加载并为该设备提供服务。
二、i2c_register_driver函数参数i2c_register_driver函数包含一个结构体参数,该结构体用于指定驱动程序的相关信息和功能。
1. struct i2c_driverstruct i2c_driver是一个定义I2C驱动程序的结构体,包含了以下重要的成员:- .driver:指向内核的struct device_driver结构体,用于描述驱动程序的信息,如名称、文件操作方法等。
- .probe:指向I2C设备探测函数的指针,用于在设备连接时进行初始化和配置。
- .remove:指向I2C设备移除函数的指针,用于在设备断开连接时进行清理和释放资源。
- .id_table:指向I2C设备ID表的指针,用于匹配设备和驱动程序。
2. I2C设备探测函数(probe函数)I2C设备探测函数是I2C驱动程序的核心功能之一,在I2C设备连接到系统时被调用。
该函数的作用是检测和初始化I2C设备,并将设备与驱动程序进行绑定。
在probe函数中,可以执行一系列必要的操作,如配置寄存器、分配内存、注册字符设备等。
Linux I2C设备驱动编写
Linux I2C设备驱动编写(一)在Linux驱动中I2C系统中主要包含以下几个成员:如果一个I2C适配器不支持I2C通道,那么就将master_xfer成员设为NULL。
如果适配器支持SMBUS 协议,那么需要去实现smbus_xfer,如果smbus_xfer指针被设为NULL,那么当使用SMBUS协议的时候将会通过I2C通道进行仿真。
master_xfer指向的函数的返回值应该是已经成功处理的消息数,或者返回负数表示出错了。
functionality指针很简单,告诉询问着这个I2C主控器都支持什么功能。
在内核的drivers/i2c/i2c-stub.c中实现了一个i2c adapter的例子,其中实现的是更为复杂的SMBUS。
SMBus 与I2C的区别通常情况下,I2C和SMBus是兼容的,但是还是有些微妙的区别的。
时钟速度对比:在电气特性上他们也有所不同,SMBus要求的电压范围更低。
I2C driver具体的I2C设备驱动,如相机、传感器、触摸屏、背光控制器常见硬件设备大多都有或都是通过I2C 协议与主机进行数据传输、控制。
结构体如下:如同普通设备的驱动能够驱动多个设备一样,一个I2C driver也可以对应多个I2C client。
以重力传感器AXLL34X为例,其实现的I2C驱动为:这里要说明一下module_i2c_driver宏定义(i2c.h):module_driver():理解上述宏定义后,将module_i2c_driver(adxl34x_driver)展开就可以得到:这一句宏就解决了模块module安装卸载的复杂代码。
这样驱动开发者在实现I2C驱动时只要将i2c_driver结构体填充进来就可以了,无需关心设备的注册与反注册过程。
I2C client即I2C设备。
I2C设备的注册一般在板级代码中,在解析实例前还是先熟悉几个定义:下面还是以adxl34x为例:这样ADXL34X的i2c设备就被注册到了系统中,当名字与i2c_driver中的id_table中的成员匹配时就能够出发probe匹配函数了。
嵌入式Linux中I2C总线驱动程序设计
Ke r s e e d d L n x I C b s I C d v c ; d v c r e ; AT 1 ywo d : mb d e ; i u ; 2 u ; 2 e i e e ie d i r v 9 RM 9 0 2 0
0 引 言
ICit - tga d i u ) 线 , 由菲利 浦 公 司开 发 的一 2 ( e i ert c ci总 n rn e r t 是 种 同步 串行 总 线 协 议 , 于 连 接 微 控 制 器 及 其 外 围 设 备 。最 用 初 是 为 音 频 和 视 频 设 备 开 发 的 ,如 今 IC在 各 种 电 子 设 备 中 2
中图法分类 号 : P9 T 3 T 3 ; P
文献标 识码 : A
文章编 号 :0 072 (0 8 1—570 10 —0 4 2 0 ) 02 1—3
De in o C u r e n e mb d e n x s se sg f 2 b s i ru d r I d v e e d dLiu y tm
IC总 线 在 传 送 数 据 过 程 中共 有 3 类 型 信 号 , 们 分 别 2 种 它 是 开 始 信 号 、 束 信 号 和 应 答 信 号( 图 l 图 2 示 ) 结 如 、 所 。
得 到 了 广 泛 的 应 用 。嵌 入 式 系 统 中 常 常 使 用 这 个 总 线 连 接
HEYa u , DE jn NGF i i e— q
( o ee f uo t nS i c n n ier g o t C ia iesyo T cn lg,G agh u 6 0 C ia C lg A tmao ce e d gn e n ,S u h v r t f eh oo y un z o 1 4 , hn) l o i n a E i h n Un i 50
Linux驱动之i2c用户态调用
一、概述I2C只有两条线,一条串行数据线:SDA,一条是时钟线SCL.正因为这样,它方便了工程人员的布线.二、用户态实现设备驱动在Linux内核代码文件i2c-dev.c中实现了I2C适配器设备文件的功能,针对每个适配器生成一个主设备号为89的设备节点(次设备号为0-255),I2c-dev.c并没有针对特定的设备而设计,只是提供了通用的read(),write(),和ioctl()等文件操作接口,在用户空间的应用层就可以借用这些接口访问挂接在适配器上的I2C设备的存储空间或寄存器,并控制I2C设备的工作方式。
i2c适配器的设备节点是/dev/i2c-x,其中x是数字。
由于适配器编号是动态分配的(和注册次序有关),所以想了解哪一个适配器对应什么编号,可以查看/sys/class/i2c-dev/目录下的文件内容。
三、用户态调用3.1、i2c-dev用户空间操作i2c,需要包含以下头文件。
打开适配器对应的设备节点i2c-dev为打开的线程建立一个i2c_client,但是这个i2c_client并不加到i2c_adapter的client链表当中。
他是一个虚拟的临时client,当用户打开设备节点时,它自动产生,当用户关闭设备节点时,它自动被释放。
3.2、ioctl()查看include/linux/i2c-dev.h文件,可以看到i2c支持的IOCTL命令1.#define I2C_RETRIES0x0701/*设置收不到ACK时的重试次数*/2.#define I2C_TIMEOUT0x0702/*设置超时时限的jiffies*/3.#define I2C_SLAVE0x0703/*设置从机地址*/4.#define I2C_SLAVE_FORCE0x0706/*强制设置从机地址*/5.#define I2C_TENBIT0x0704/*选择地址位长:=0for7bit,!=0for10bit*/6.#define I2C_FUNCS0x0705/*获取适配器支持的功能*/7.#define I2C_RDWR0x0707/*Combin ed R/W transfer(one STOP only)*/8.#define I2C_PEC0x0708/* !=0to use PEC with SMBus*/9.#define I2C_SMBUS0x0720/*SMBus transfer*/例如:1、设置重试次数:ioctl(fd, I2C_RETRIES,m);设置适配器收不到ACK时重试的次数为m。
linux i2c bus unit address format error -回复
linux i2c bus unit address format error -回复主题:Linux I2C总线单元地址格式错误引言:在使用Linux操作系统的嵌入式系统开发中,I2C总线是一种常见的串行通信协议,用于连接主控设备与外设,如传感器、存储器等。
每个I2C 设备都有一个唯一的7位或10位地址,用于在总线上进行通信。
然而,在使用Linux驱动程序操作I2C设备时,可能会遇到I2C总线单元地址格式错误的问题。
本文将一步一步回答关于该错误的解决方法。
I2C总线单元地址格式错误:在Linux系统中,使用i2c-tools等工具可以通过命令行或C语言编程进行I2C设备的控制与通信。
但在进行I2C设备操作时,往往需要指定设备的地址,以便与设备进行通信。
I2C设备的地址包括总线地址和设备地址,而错误的地址格式会导致通信失败或数据读写错误。
步骤一:验证设备的正确地址首先,我们需要确认所连接的I2C设备的正确地址。
可以通过i2cdetect命令来检测设备的地址。
在终端中运行以下命令:i2cdetect -y <bus>这里的`<bus>`是I2C总线的编号,通常是0或1。
该命令会在终端中打印出已连接设备的地址列表。
根据打印结果,确认设备的地址是否与预期一致。
步骤二:检查设备地址格式在Linux中,设备地址是采用十六进制格式表示的。
且根据不同的I2C设备和驱动程序要求,地址的位数可能有所不同,通常为7位或10位地址。
对于7位地址,地址范围为0x00至0x7F,其中最低位第0位是保留位(R/W位),负责指示读或写操作。
其他7位(第1至第7位)则是设备的地址。
如果设备的地址是0x50,那么在使用命令或代码操作时,应该将其表示为0x28,即去除了最低位的保留位,并将剩余的7位地址转换为十六进制。
对于10位地址,地址格式有所不同。
前两个字节是保留位(第0至第1位),接下来的八位是设备地址(第2至第9位)。
LinuxI2C驱动整理(以RK3399Pro+Kernel4.4为例)
LinuxI2C驱动整理(以RK3399Pro+Kernel4.4为例)⼀. Linux I2C驱动架构Linux内核⾥,I2C驱动框架可以分为两层,adapter驱动和deivce驱动。
Adapter驱动也可以理解为I2C总线驱动,指的是SOC⾥的I2C控制器驱动。
⼀个SOC可能包含多个I2C控制器,⽽每个控制器的使⽤⽅式是相同的(寄存器参数、收发数据的⽅法等),因此多个控制器可以共⽤⼀套adapter驱动;Deivce驱动,对应的是SOC外围的I2C设备,不同类型I2C设备需要开发不同的设备驱动,同⼀类型的I2C设备可以使⽤⼀种驱动,但是每⼀个I2C设备都由⼀个唯⼀的client来描述。
⼆. Adapter配置DTSI⽂件(kernel/arch/arm64/boot/dts/rockchip/rk3399.dtsi)描述了RK3399Pro所有的I2C控制器信息:i2c0: i2c@ff3c0000 {compatible = "rockchip,rk3399-i2c";reg = <0x00xff3c00000x00x1000>;clocks = <&pmucru SCLK_I2C0_PMU>, <&pmucru PCLK_I2C0_PMU>;clock-names = "i2c", "pclk";interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH 0>;pinctrl-names = "default";pinctrl-0 = <&i2c0_xfer>;#address-cells = <1>;#size-cells = <0>;status = "disabled";};i2c1: i2c@ff110000 {compatible = "rockchip,rk3399-i2c";reg = <0x00xff1100000x00x1000>;clocks = <&cru SCLK_I2C1>, <&cru PCLK_I2C1>;clock-names = "i2c", "pclk";interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH 0>;pinctrl-names = "default";pinctrl-0 = <&i2c1_xfer>;#address-cells = <1>;#size-cells = <0>;status = "disabled";};i2c2: i2c@ff120000 {compatible = "rockchip,rk3399-i2c";reg = <0x00xff1200000x00x1000>;clocks = <&cru SCLK_I2C2>, <&cru PCLK_I2C2>;clock-names = "i2c", "pclk";interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH 0>;pinctrl-names = "default";pinctrl-0 = <&i2c2_xfer>;#address-cells = <1>;#size-cells = <0>;status = "disabled";};i2c3: i2c@ff130000 {compatible = "rockchip,rk3399-i2c";reg = <0x00xff1300000x00x1000>;clocks = <&cru SCLK_I2C3>, <&cru PCLK_I2C3>;clock-names = "i2c", "pclk";interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH 0>;pinctrl-names = "default";pinctrl-0 = <&i2c3_xfer>;#address-cells = <1>;#size-cells = <0>;status = "disabled";};i2c5: i2c@ff140000 {compatible = "rockchip,rk3399-i2c";reg = <0x00xff1400000x00x1000>;clocks = <&cru SCLK_I2C5>, <&cru PCLK_I2C5>;clock-names = "i2c", "pclk";interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH 0>;pinctrl-names = "default";pinctrl-0 = <&i2c5_xfer>;#address-cells = <1>;#size-cells = <0>;status = "disabled";};i2c6: i2c@ff150000 {compatible = "rockchip,rk3399-i2c";reg = <0x00xff1500000x00x1000>;clocks = <&cru SCLK_I2C6>, <&cru PCLK_I2C6>;clock-names = "i2c", "pclk";interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH 0>;pinctrl-names = "default";pinctrl-0 = <&i2c6_xfer>;#address-cells = <1>;#size-cells = <0>;status = "disabled";};i2c7: i2c@ff160000 {compatible = "rockchip,rk3399-i2c";reg = <0x00xff1600000x00x1000>;clocks = <&cru SCLK_I2C7>, <&cru PCLK_I2C7>;clock-names = "i2c", "pclk";interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH 0>;pinctrl-names = "default";pinctrl-0 = <&i2c7_xfer>;#address-cells = <1>;#size-cells = <0>;status = "disabled";};i2c4: i2c@ff3d0000 {compatible = "rockchip,rk3399-i2c";reg = <0x00xff3d00000x00x1000>;clocks = <&pmucru SCLK_I2C4_PMU>, <&pmucru PCLK_I2C4_PMU>;clock-names = "i2c", "pclk";interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH 0>;pinctrl-names = "default";pinctrl-0 = <&i2c4_xfer>;#address-cells = <1>;#size-cells = <0>;status = "disabled";};i2c8: i2c@ff3e0000 {compatible = "rockchip,rk3399-i2c";reg = <0x00xff3e00000x00x1000>;clocks = <&pmucru SCLK_I2C8_PMU>, <&pmucru PCLK_I2C8_PMU>;clock-names = "i2c", "pclk";interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH 0>;pinctrl-names = "default";pinctrl-0 = <&i2c8_xfer>;#address-cells = <1>;#size-cells = <0>;status = "disabled";};可以看出,该SOC共有9个I2C控制器,分别为I2C0~I2C8, 每个控制器对应了不同的寄存器基地址(例如I2C0对应0xff3c0000),它们的compatible匹配属性都是"rockchip,rk3399-i2c",也就是对应了同⼀个adapter驱动。
linux下i2c接口的电容触摸屏驱动开发
原文地址:电容触摸屏2011-01-14 15:361.Kconfig文件增加宏定义2.Makefile文件增加编译处理3.添加程序源码Touch screen remote control design document2010年11月08日星期一 13:08Touch screen remote control design document1. 开发板环境a) Mini2440 开发板。
Arm9 处理器+64M SRAM + 64M Flash +3.5’触摸屏LCDb) Linux 2.6.32 kernel,支持多点触摸触摸屏+Qtopia 2.2.20 图形用户界面系统c) AVR 单片机+加速度传感器+红外一体化接收头+红外发射二极管2. 主机开发环境a) Vmware 6.0 安装 Fedora 10 系统,按照友善之臂mini2440 使用手册来建立开发环境。
最好在安装fedora 10的过程中将所有的可选项全部安装,以免后续开发过程中遇到不可预知的问题。
Fedora 10默认不能以root用户登陆图形用户界面,需要以普通用户登陆之后在命令终端中su切换到root用户,然后修改文件/etc/pam.d/gdm。
将auth required pam_succeed_if.so user != root quiet 这句注销。
b) 按照友善之臂用户手册建立交叉开发环境。
安装arm-linux-gcc4.3.2,arm-qtopia, x86-qtopia, root-qtopia, linux-2.6.32-friendlyarm 到系统中。
安装的过程中有一个问题是,不能够同时编译arm-qtopia和x86-qtopia,如果这样做,会发生不可预知的错误。
典型问题是qt2的designer打开后是透明的,无法操作。
c) 遥控器解码目前采用FPGA平台来完成的,所以主机具有FPGA开发环境(quartus9.0)d) 红外发射和加速度传感器的手势操作室通过AVR单片机完成的,所以主机具有AVR单片机开发环境(Keil 4)3. 图形界面编码a) Arm-qtopia 文件夹中安装了qt2,在qt2的bin目录下执行 designer 就可以进入qt的图形开发界面。
i2c_register_driver函数详解
i2c_register_driver函数详解一、概述i2c_register_driver函数是Linux内核中用于注册I2C设备驱动的函数之一。
它用于将设备驱动程序注册到内核,以便其他模块可以使用该驱动程序来与I2C设备进行通信。
二、函数原型int i2c_register_driver(struct i2c_driver *driver);三、函数参数说明* driver:指向i2c_driver结构体的指针,该结构体包含了设备驱动的相关信息,如设备名称、设备ID等。
四、函数返回值如果函数成功注册驱动程序,则返回0;否则返回-E...等错误代码。
五、函数功能详解i2c_register_driver函数将指定的i2c_driver结构体注册到内核中,使其成为可用的I2C设备驱动。
在注册驱动程序之前,需要确保驱动程序已经正确编译并包含在内核中。
在注册驱动程序时,i2c_register_driver函数会执行以下操作:1. 检查驱动程序是否符合内核的要求,如设备ID、设备名称等是否正确。
2. 将驱动程序的信息添加到内核的设备列表中,以便其他模块可以找到并使用该驱动程序。
3. 注册成功后,内核会为该驱动程序分配相应的资源,如内存、端口等,并建立与I2C总线的连接。
六、使用示例```c#include <linux/module.h>#include <linux/i2c.h>struct i2c_driver my_driver;int main(){int ret;ret = i2c_register_driver(&my_driver);if (ret) {printk(KERN_ERR "Failed to register driver: %d\n", ret);return ret;}// 其他操作...return 0;}```在上述示例中,首先定义了一个i2c_driver结构体变量my_driver,用于存储驱动程序的相关信息。
rk linux下i2c总线驱动读写原理
RK Linux下I2C总线驱动读写原理RK Linux,一个开源的、强大的、可定制的操作系统,广泛应用于各种嵌入式系统。
I2C总线是一种常用的通信协议,常用于连接低速外围设备,如传感器、EEPROM等。
在RK Linux下,I2C总线驱动的读写原理是什么呢?首先,我们来了解下I2C总线的基本概念。
I2C总线是一种双线串行通信总线,由数据线SDA和时钟线SCL组成。
通过这两根线,多个设备可以在同一总线上进行通信。
每个设备都有一个唯一的地址,主机可以通过发送设备的地址来选择与之通信的设备。
在RK Linux下,I2C总线驱动的读写操作主要依赖于内核提供的API。
这些API 包括i2c_read()、i2c_write()等,它们提供了与I2C设备通信的接口。
那么,这些API是如何实现读写操作的呢?在内核中,I2C驱动程序负责管理I2C总线上所有的设备和它们的通信。
当需要从设备读取数据时,驱动程序首先会向设备发送读请求。
设备接收到请求后,会将数据写入SDA线。
驱动程序会持续监听SDA线,一旦接收到数据,就会将其保存并通知应用程序。
同样地,当需要向设备写入数据时,驱动程序会向设备发送写请求。
设备接收到请求后,会准备好接收数据。
驱动程序会将数据写入SDA线,设备接收到数据后,会将数据保存到内部寄存器中。
需要注意的是,I2C总线的读写操作都是通过驱动程序来完成的。
应用程序只需要调用内核提供的API即可与I2C设备进行通信。
这样设计的好处是应用程序可以专注于自己的业务逻辑,而不需要关心底层的通信细节。
同时,这也使得应用程序与具体的I2C设备无关,具有更好的可移植性和扩展性。
Linux下基于I2C总线的CAT1025设备驱动实现
1
IC总线 接 口 2
L 2 0 微 控 制 器 是 基 于 一 个 支 持 实 时 仿 真 和 嵌 入 跟 踪 的 3 /1 位 ARM7 PC 21 2 6 TD 集 成 了 两 路 高 速 IC 总 线 , 2 与 IC 总 线 接 口 有 关 的 专 用 寄 存 器 有 以 下 : 2
21 0 1年 4月
枣庄学 院学报
J OUR AL O AO HUAN I E 盯Y N FZ Z G UN V RS
Ap . 01 r2 1
第2卷 8
第 2期
V0 . 8 NO. 12 2
Ln x下 基 于 IC总 线 的 C T 5设 备 驱 动 实 现 iu 2 A 12 0
王 莹
( 枣庄学院 计算机科学 系, 山东 枣庄 27 6 ) 7 10
[ 摘
要] 本文介绍 了 L C 20处 理器 IC总线 的工作 原理 , P21 2 分析 了嵌 入式 l u i x内核 中 IC总线驱动的体 系结 构和各 n 2
个模块 的功能. 结合具体 的 IC接 口的存储器和 电源监 控的完 全解决 方案 C T 05芯 片 , 细给 出了嵌入式 l u 2 A 12 详 i x下 n 基于 IC总线 C T 0 5设备驱动程序 的开发过 程. 2 A 12 [ 关键词 ]2 IC总线 ; 设备驱动 ; A 12 ; C T 05 嵌入式 Lnx iu [ 中图分类 号] P 7 T24 [ 文献标识码 ] A ① [ 文章编号 ]04— 07 2 1 )2—08 0 10 7 7 (0 1 0 0 7— 5
1I 总 线 连 接 图 . 2C
12 IC 时 序 信 号 . 2
①
[ 收稿 日期] 0 0 1 — 6 2 1 — 1 1 [ 作者简介] 王莹 ( 92一 , , 枣庄人 , 学院计算机科 学系助 教, 1 8 ) 女 山东 枣庄 工学硕 士, 主要研究方 向 : 嵌入式 系统及 其应用 , 机 器人控制.
linux下i2c-switch
Linux 下i2c switch pca9548驱动作者:韩大卫@吉林师范大学现有的关于i2c switch 资料非常少。
即使阅读完官方的datasheet.也不能写出完全正确的操作。
因为内核中的驱动本身不是那么完善的。
还有一些资料是单片机编程的,可惜在linux上并不能成功执行。
pca954x 系列是一种i2c switch 芯片,比如pca9548 可实现8个开关,进而实现多了8条i2c 通道。
这样可以在有限的i2c 资源上扩展出足够多的接口。
解决了在使用i2c总线容量的问题。
Pca954x 内部只有一个控制寄存器。
属于无子地址设备。
做I/O 访问时,只需要向0x00 地址处做写操作即可,这就可实现pca954x 下挂设备i2c bus 的选路。
但是在现有的pca954x 驱动函数中,没有实现自动对内部控制寄存器进行相应配置,这样的话就需要额外的写一个附加的配置函数,实现这种功能。
如果没有这种配置函数,只是使用现有的内核代码,那么会出现有一些难以发现的问题,但是还是被我遇到了。
在我看来,这种问题暂且不能算bug,但至少应该去优化,毕竟,如果每次在访问不同的i2c bus 时,需要我们手动的去操作i2c switch 的开关,这多少会影响执行效率,代码量变大。
还有一点,我们自己编写的配置函数,是严重依赖于硬件的,即我们的开关位置打开的位置需要自己判断,在代码上固定写出,可移植性差。
稍后可以在我的代码中看到这种缺陷。
基于以上原因,我认为pca954x 的驱动应该修改。
有时间的话我会整理出自己的代码,融入到内核代码中去,再提供出API 供大家使用。
I2C 1 地址0x71,0x72,0x73 上都是pca9548 , 每个pca9548上挂了8 个千兆以太网光模块sfp。
这样我们系统上就可以同时挂载24 个千兆以太网光模块sfp。
I2C 0 地址0x70 也是pca9548,挂了2个万兆以太网光模块XFP,还有3个温度传感器TMP411.*********** ***************下面的内容是i2c bus 选路函数。
Linux下读写芯片的I2C寄存器
Linux下读写芯⽚的I2C寄存器要想在Linux下读写芯⽚的I2C寄存器,⼀般需要在Linux编写⼀份该芯⽚的I2C驱动,关于Linux下如何编写I2C驱动,前⼀篇⽂章已经做了初步的介绍,并且留下了两个疑问尚未解决,第⼀个是如何对Linux提供的I2C操作函数进⾏进⼀步封装,实现对芯⽚寄存器的读写;另⼀个是如何在⽤户空间调⽤该I2C驱动代码。
本⽂将讨论前⼀个问题。
⾸先,我们要了解Linux系统提供的I2C操作函数怎么使⽤,上篇⽂章已经提到过,对I2C设备的读写,Linux系统提供了多种接⼝,这些接⼝可以在内核的 i2c.h 中找到,这⾥我主要介绍下⾯这组读写接⼝:extern int i2c_master_send(struct i2c_client *,const char* ,int);extern int i2c_master_recv(struct i2c_client *,char* ,int);第⼀个参数是 i2c_client 对象指针,第⼆个参数是要传输的数据buffer指针,第三个参数为buffer的⼤⼩。
接⼝函数已经有了,下⾯我们要解决的问题就是以何种形式/规则去使⽤这些接⼝才能正确地读写芯⽚的相关寄存器。
⾸先,我们需要查询芯⽚⼿册,找到芯⽚⼿册中,关于寄存器的I2C读写时序,其实,⼤多数芯⽚的I2C寄存器的读写时序都是⼀样的,下⾯我还是以⼿头的TVP5158芯⽚为例。
⾸先分析写操作,该芯⽚的⼿册中给出的I2C寄存器写时序图如下:从上图可以看出,真正需要执⾏写操作的有两处,Step4 和 Step6 ,Step4⾸先写⼊寄存器的偏移地址,⽽Step6则是写⼊到该寄存器的值。
由此已经很清楚了,对于写I2C寄存器,我们需要做的就是给 i2c_master_send 函数传⼊两个字节的数据即可,第⼀个字节为寄存器的地址,第⼆个字节为要写⼊寄存器的数据。
⽰例如下:static int tvp5158_i2c_write( struct i2c_client* client,uint8_t reg,uint8_t data){unsigned char buffer[2];buffer[0] = reg;buffer[1] = data;if( 2!= i2c_master_send(client,buffer,2) ) {printk( KERN_ERR " tvp5158_i2c_write fail! \n" );return -1;}return 0;}其实挺简单的,没有什么复杂的代码。
linux下8025T iic(I2C)驱动源代码
}
if (NULL == reg_addr && NULL != tmp ){
kfree( tmp );
printk( KERN_INFO "----kmalloc()--error--\r\n" );
return -ENOMEM;
ret,reg[0],reg[1],reg[2],reg[3],reg[4],reg[5],reg[6],reg[7] );
}
return ret;
}
static int _8025t_detach(struct i2c_adapter *adap)
{
return 0;
printk( KERN_INFO "----i2c_attach_client()--error--\r\n" );
}
printk( KERN_INFO "----_8025t_attach()--end--\r\n" );
return 0;
}
static int _8025t_probe( struct i2c_adapter *adapter )
}
memset( tmp, 0x00, count );
memset( reg_addr, 0x00, count );
reg_addr[0] = buf[0];
tmp[0] = buf[0];
msg[0].addr = p_bห้องสมุดไป่ตู้nk->client.addr;
}
char reg[]={0x00,0x30,0x30,0x10,0x30,0x20,0x08,0x10};
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
linux i2c驱动1. i2c-dev interfaceI2C dev-interface通常,i2c设备由某个内核驱动控制。
但是在用户空间,也可以访问某个I2C设备:你需要加载i2c-dev模块。
每个被注册的i2c适配器(控制器)会获得一个数字号,从0开始。
你可以检查/sys/class/i2c-dev,来查看适配器对应哪个数字号。
你也可以通过命令"i2cdetect -l"获取你的当前系统的所有I2c适配器的列表。
i2cdetct是i2c-tool包中的一个工具。
i2c设备文件是字符设备,主设备号是89,次设备号的分配如上所述。
设备文件名通常被规定为"i2c-%d"(i2c-0, i2c-1, ...,i2c-10, ...)i2c设备文件是字符设备,主设备号是89,次设备号的分配如上所述。
设备文件名通常被规定为"i2c-%d"(i2c-0, i2c-1, ...,i2c-10, ...).所有256个次设备号都保留给i2c使用。
C example=========假定你要在你的C应用程序中访问i2c适配器。
第一件事情就是包含头文件"#include<linux/i2c-dev.h>"。
注意,存在两个"i2c-dev.h"文件: 一个属于Linux kernel,用于内核驱动中;一个由i2c-tools发布,用于用户程序。
显然,这里需要使用第二个i2c-dev.h文件。
现在,你需要确定访问哪个适配器。
你需要通过查看/sys/class/i2c-dev/或者运行"i2cdetect -l"确定。
适配器号时常是动态分配的,你无法预先假定某个值。
因为它们甚至会在系统重启后变为不同的值。
下一步,打开设备文件,如下:int file;int adapter_nr = 2; /*probably dynamically determined */char filename[20];snprintf(filename, 19, "/dev/i2c-%d", adapter_nr);file = open(filename, O_RDWR);if (file < 0) {/* ERROR HANDLING; you can check errno to see what went wrong */ exit(1);}当你打开设备后,你必须明确说明你相与哪个设备地址进行通信:int addr = 0x40;if (ioctl(file, I2C_SLAVE, addr) < 0) {/* ERROR HANDLING; you can check errno to see what went wrong */ exit(1);}Well, 你现在准备好与I2C设备通信了。
你现在可以使用SMBus命令集或者无格式I2C(plain I2C)与你的设备进行通信。
如果设备支持SMB协议,则SMBus命令集优先选择。
代码如下:__u8 register = 0x10; /* Device register to access */__s32 res;char buf[10];/* Using SMBus commands */res = i2c_smbus_read_word_data(file, register);if (res < 0) {/* ERROR HANDLING; you can check errno to see what went wrong */ } else {/* res contains the read word */}/* Using I2C Write, equivalent ofi2c_smbus_write_word_data(file, register, 0x6543) */buf[0] = reister;buf[1] = 0x43;buf[2] = 0x65;if (write(file ,buf, 3) != 3) {/* ERROR HANDLING: i2c transaction failed */}/* Using I2C Read, equivalent of i2c_smbus_read_byte(file) */if (read(file, buf, 1) != 1) {/* ERROR HANDLING: i2c transaction failed */} else {/* buf[0] contains the read byte */}注意,仅有I2C和SMBus协议的一部分子集功能可以通过read()和write()的调用完成。
尤其,对于组合型的传输(mixing read and write messages in the same transaction)不被read()/write()支持。
基于这个原因,read()和write()这两个接口几乎不被用户空间程序使用。
IMPORTANT: because of the use of inline functions, you *have* to use '-O" orsome variation when you compile your program!Full interface description==========================IOCTLs定义如下:ioctl(file ,I2C_SLAVE, long addr)Change slave address. The address is passed in the 7 lower bits of the argument (except for 10 bit addresses, passed in the 10 lower bits in this case)ioctl(file, I2C_TENBIT, long select)Selects ten bit addressed if select not equals 0, selects normal 7 bit addresses if select equals 0. Default 0. This request is only valid if theadapter has I2C_FUNC_10BIT_ADDR.ioctl(file, I2C_PEC, long select)Selects SMBus PEC (packet error checking) generation and verification if select not equals 0, disables if select equals 0. Default 0.Used only for SMBus transactions. This request only has an effect if the adapter has I2C_FUNC_SMBUS_PEC; it is still safe if not, it just doesn't haveany effect.ioctl(file, I2C_FUNCS, unsigned long *funcs)Gets the adapter functionality and puts it in *funcs.ioctl(file, I2C_RDWR, struct i2c_rdwr_ioctl_data *msgset)Do combined read/write transaction without stop in between. Only validif theadatpter has I2C_FUNC_I2C. The argument is a pointer to astruct i2c_rdwr_ioctl_data {struct i2c_msg *msgs; /* ptr to array of simple messages */int nmsgs; /* number of messages to exchanges */}msgs[]包含指向data buffer的指针。
此函数调用会根据每个message中的I2C_M_RD flag的设置向buffer写或者读数据。
在每个message里,slave address和是否使用ten-bit-address必须设置。
ioctl(file, I2C_SMBUS, struct i2c_smbus_ioctl_data *args)Not meant to be called directly; instead, use the access functions below.你可以通过使用read(2)和write(2)调用来进行无格式i2c传输。
在访问设备前通过ioctlI2C_SLAVE来设置地址。
你可以使用SMBus级传输(see documentation file smbus-protocol for details),通过如下函数调用:__s32 i2c_smbus_write_quick(int file, __u8 value);__s32 i2c_smbus_read_byte(int file);__s32 i2c_smbus_write_byte(int file, __u8 value);__s32 i2c_smbus_read_byte_data(int file, __u8 command);__s32 i2c_smbus_write_byte_data(int file, __u8 command, __u8 value); __s32 i2c_smbus_read_word_data(int file, __u8 command);__s32 i2c_smbus_write_word_data(int file, __u8 command, __u16 value); __s32 i2c_smbus_process_call(int file, __u8 comand, __u16 value); __s32 i2c_smbus_read_block_data(int file, __u8 command, __u8*values);__s32 i2c_smbus_write_block_data(int file, __u8 command, __u8 length, __u8 *values);所有上述传输失败时返回-1;你可以读取errno来检查具体错误信息。