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函数中,可以执行一系列必要的操作,如配置寄存器、分配内存、注册字符设备等。
- 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来检查具体错误信息。