I2C(Inter-Integrated Circuit)总线是一种串行数据传输协议,被用于连接芯片之间的通信。在Linux内核中,i2c子系统驱动负责管理I2C总线,允许多个设备通过同一条总线进行通信。本文将介绍Linux内核i2c子系统驱动的相关知识。
一、i2c子系统驱动的结构
在Linux内核中,i2c子系统驱动通常包含以下几个结构:
1. i2c_adapter结构体
i2c_adapter结构体描述了一条I2C总线的特性,包括总线地址、时钟频率、数据传送方式等。该结构体的定义在i2c.h头文件中,如下所示:
struct i2c_adapter {
struct module *owner;
const char *name;
struct bus_type *bus;
u32 algo_data;
struct i2c_algorithm *algo;
void *algo_priv;
struct device dev;
unsigned long algo_data_dma;
unsigned long owndata;
unsigned int timeout;
unsigned int retries;
bool (*unrecoverable)(struct i2c_adapter *, struct i2c_msg *);
int (*setup)(struct i2c_adapter *);
void (*shutdown)(struct i2c_adapter *);
int (*bus_recovery)(struct i2c_adapter *);
void *adapdata;
struct i2c_lock_operations *lock_ops;
const struct of_device_id *of_match_table;
2. i2c_algorithm结构体
i2c_algorithm结构体定义了I2C总线中的通信算法,包括数据传输格式、地址范围等。该结构体的定义在i2c.h头文件中,如下所示:
struct i2c_algorithm {
int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs,
int (*bus_xfer)(struct i2c_adapter *adapter, u16 addr,
unsigned short flags, char read_write,
u8 command, int size, union i2c_bus_data *data);
int (*master_recv)(struct i2c_adapter *adap, struct i2c_msg *msgs,
int (*master_send)(struct i2c_adapter *adap, struct i2c_msg *msgs,
u32 (*functionality)(struct i2c_adapter *);
struct module *owner;
const char *name;
3. i2c_driver结构体
i2c_driver结构体描述了一个i2c设备的特性,包括设备类型、ID等信息。该结构体的定义在i2c.h头文件中,如下所示:
struct i2c_driver {
unsigned int class;
const struct i2c_device_id *id_table;
int (*probe)(struct i2c_client *, const struct i2c_device_id *);
int (*remove)(struct i2c_client *);
void (*shutdown)(struct i2c_client *);
int (*suspend)(struct i2c_client *, pm_message_t state);
int (*resume)(struct i2c_client *);
const struct i2c_device_id *of_match_table;
const struct of_device_id *of_match_table;
struct device_driver driver;
4. i2c_client结构体
i2c_client结构体描述了一个具体的i2c设备,包括设备地址、设备类型、驱动等信息。该结构体的定义在i2c.h头文件中,如下所示:
struct i2c_client {
unsigned short flags;
unsigned short addr;
char name[I2C_NAME_SIZE];
struct device dev;
struct i2c_adapter *adapter;
struct i2c_driver *driver;
void *algo_data;
struct i2c_board_info const *board_info;
二、i2c子系统驱动的通信过程
i2c子系统驱动的通信过程需要经过以下步骤:
1. 注册i2c_adapter
初次使用I2C总线时,需要先注册i2c_adapter结构体,告诉内核I2C总线的特性。在Linux内核中,注册i2c_adapter结构体可以使用i2c_add_adapter函数来完成。
2. 注册i2c_driver
为了能够与具体的i2c设备通信,需要先注册i2c_driver结构体。在Linux内核中,注册i2c_driver结构体可以使用i2c_add_driver函数来完成。
3. 连接i2c_client设备
一旦I2C总线被注册成功,可以使用i2c_new_device函数连接一个i2c_client设备。在连接设备时,需要指定设备地址、设备类型等信息。
4. 与设备通信
当i2c_client设备连接成功后,就可以使用该设备进行I2C通信了。在Linux内核中,I2C数据的传输通常使用i2c_transfer函数进行。该函数需要传入一个指向i2c_msg结构体的指针,该结构体用于描述数据的传输信息。
5. 注销i2c_driver和i2c_adapter
当使用完i2c_driver和i2c_adapter之后,需要使用i2c_del_driver和i2c_del_adapter函数来注销。
三、i2c子系统驱动的应用场景
i2c子系统驱动在Linux内核中的应用广泛,包括但不限于以下场景:
1. 屏幕显示
在Linux内核中,i2c子系统驱动可用于控制显示器的点阵屏幕,比如树莓派的OLED屏幕等。
2. 触摸屏
i2c子系统驱动还可用于连接触摸屏设备,实现触摸控制。
3. 传感器
i2c子系统驱动也可以用于连接各种传感器设备,如温度传感器、气压传感器等。这些设备通常需要I2C总线进行数据传输。
i2c子系统驱动在Linux内核中的应用范围广泛,是连接各种设备的重要手段。通过对i2c子系统驱动的深入了解,可以更好地开发和使用相关设备。
相关问题拓展阅读:
求教怎么学习linux内核驱动
1. 分享Linux内核学习和驱动开发的经验。
内核逗戚学习
Linux 内核功能越来越完善,如果没有充裕的时间,深入内核并不是很现实。所以建议先读一本内核的书,
之一遍是读,会读的很迷糊;之后反省一下,然后再浏览一下;可以想象一个 OS 是如何运行的,这样可以不
陷入 Linux 内核的细节;最后可以深入自己感兴趣或者需要的那一子系统
推荐 《Linux Kernel Development》
即便是子系统,也是很庞大的。一个省力的方式是网上搜一些相关的文章,便于快速了解这个子系统的运作;
然后结合代码,形成自己的认知,最后做一下总结。如果仅仅是快速了解某一子系统的运作,可以参考一些早期
代码的注解书籍,再深入的时候看看最新的代码实现
对内核的认知是一个反复的过程,一开始并不完善,可能需要反复纠正。不要陷入这种纠错中;而是以后继续
使用和学习过程中,发现了没有弄清楚的地方再深入,毕竟 Linux 内核是不断变化的
还有一个很好的方式是,从系统调用入手,现在这方面的数据不少,而且对系统调用的语义都有讲解,这样可以
间接了解 Linux 系统的一些概念。对系统调用熟悉了,可以根据系统调用的执行过程,来大体了解内核的一个
运作过程;但是跟踪系统调用的时候要注意抓主线,现在内核系统很复杂,一些 code path 上可能会涉及多个
子系统,可以从名字上猜测它们是干什么的,不需要深入,否则会发现精力完全被分散掉了
学习 Linux 内核,一个很重要的是抽象的能力,所谓的抽象这里仅仅是指分清接口和接口的实现。因为 Linux
内核子系统很多,有很多子系统相互渗透,这样 code path 看上去很复杂。阅读代码的时候,为了排除干扰,
需要分清哪些是自己需要看的,哪些是其它子系统的接口,对于其它子系统的接口,先当作它们功能完善不会
出问题好了,这样可以关注重点;打个比方,一个应用程序的代码可能量很大,比如一个 apache 项目,它
包含很多组件,有时候阅读代码的时候会看到不同组件的 API,深入看相关组件实现并不现实,这时候分清主次
对于代碰孝码的阅读就很有帮助了,总不能看到了 malloc 就要先把它的实现弄清楚吧,系统调用多者呢
推荐书籍
OReilly.Linux.System.Programming.2nd.Edition
The.Linux.Programming.Interface
驱动开发
一直围绕 服务器 做,接触的比较多的是网卡驱动。最开始想着从上到下,好好学习协议栈,后来发现内容太多,
进展太慢。后来参考一些驱动开发方面的书籍,把驱动独立开,使用内核提供的接口,就类似写应用的时候很多
情况下只需要了解系统接口和库函数的原型描述而不需要继续深入一样。这样把自己从内核复杂的实现细节中解
放出来,可以重点看网卡的特性部分;之后可以再深入了解设备的运作过程,比如网卡的收发包在协议栈中的

位置和运作
个人感觉如果工作中能接触驱动开发更好,否则很多情况下,有的设备并不常见,比如 Infiniband 卡
现在民用设备越来越广泛,可以选择自己感兴山吵陵趣而手头又容易有的设备进行研究,比如无线网卡、wifi 等
驱动开发,一定要先专注一个设备,从头到尾熟悉一遍,然后总结驱动开发是怎样的、驱动是如何关联到系统中
的、Linux 采用什么样的分层模式来提供对多种多样设备的支持,如类似 VFS 一样的抽象分层
推荐
linux device driver, 3rd edition
Linux设备驱动开发详解
2. 您觉得Linux驱动开发的难点是什么,有什么好的方法来克服?
Linux 内核对各种设备的驱动开发提供了完善的框架支持,对应某个驱动,把对外的接口弄清楚就可以了。打个
比方,一个设备可能在不同的 OS 上需要支持,比如 FreeBSD/windows 等,每个 OS 都有自己定义的接口,
设备的驱动定义好与这些 OS 接口的连接,剩下的就是设备本身的特性管理以及驱动接口中对设备管理函数的调
用了,比如寄存器访问、配置管理、缓冲区管理、数据收发等,比较重要的中断和同步的控制,要避免数据处理的
时候的死锁。
比如网卡驱动,基本的要求是提供内核需要的接口,这样网卡驱动才能挂接到系统中,剩下的就是接口需要调用
网卡驱动的内部函数,来对网卡进行控制、数据收发和管理等
Linux 支持的设备种类繁多,不可能所有都掌握,某一子系统也只能是熟悉,因为同类设备还有许多自由的特性。
写驱动的步骤可以概括为:
) 阅读设备规范,对设备的运行机理有所了解
为了减少干扰,不考虑要支持的 OS,独立与 OS 考虑基本的功能如何实现
) 参考同类设备在 Linux 内核中的驱动架构
) 提供基本的 Linux 设备驱动接口和实现设备的基本功能,比如网卡收发小数据量
) 在性能上逐步提示,比如网卡传输的数据量加大、中断及时处理、避免死锁等
) 对边界条件进行完善,网卡上就是对一些特殊大小的数据包传输完善等
) 对设备进行更高级控制的支持,比如网卡支持 ethtool 等工具
) 反复调试、改进和优化
3. Linux内核有上百个驱动子系统,你研究过内核各种驱动子系统的共性,层次结构设计吗?分享学习一个Linux内核子系统的经验,例如USB、I2C、HID等driver。
每一个子系统都巨大无比,而且涉及各种硬件规范,很难去搞明白所有。只能是遇到问题的时候,
能对某一部分深入下去。之前了解过 SCSI 的架构,最上层的抽象,中间层的桥梁,更底层的设备
驱动控制
如果仅仅是做 driver 的工作,可以把精力放在设备特性上,Linux 内核部分只需要了解驱动
接口和同步、内存管理等基本功能
4. 您深入研究过Linux设备驱动模型,关注过Linux内核驱动的设计思想吗?
Linux 设备驱动模型是从分类的角度来看待设备,分类是多维的,所以 /sys 下也是多个目录
另外,设备驱动模型给出了系统中设备布局信息,比如根据总线地址可以定位对应的设备目录等
Linux 内核驱动可以都是遵循一个逐层抽象的架构:
最上层的抽象层便于系统软件的访问,
中间层的实现硬件协议细节,同时提供上下两层连接的接口,
对于最下层的 driver 来说就是要定义底层驱动要实现的接口和实际的设备控制
由于 Linux 内核各类驱动的框架支持,driver 可以更加关注设备本身的特性
5. Android系统是基于Linux内核的,传统的Linux驱动开发和Android驱动开发有什么区别?
传统的 Linux 内核驱动开发,只需要定义好 Linux 需要的驱动接口就好了,之后
专注与设备本身的特性
而 Android 驱动开发,需要将设备操作接口继续封装,提供上层使用的 Java API;
driver 部分可以使用 C 代码,一些更复杂的操作可以用 Java 实现,然后 driver
提供对复杂操作的接口支持
一个很重要的方面是功能的分离定义,比如哪些是 driver 实现的,哪些是上层实现的,
它们之间的接口是怎样的,定义好这些,就可以按照传统 driver 的实现方式来做了;
从某种程度上,可以看作是传统 driver 跟相关 tools 转换成了 Android driver
和上层 Java 接口
1.首先要了解为什么要学习内核?下图已表明,如果要从事驱动开发或系统研究,就要学习内核。
2.内核的知识就像下面的绳结一样,一环余或携扣一环,我们要解开它们,就必须要先找到线头也就是内核中的函数竖伏接口。初学阶段,我们一般不深入的研究内核代码,会使用内核的接口函数就不错了。
3.下面提供了如何学习这些内核函数的方法,就像解绳子一样
4.学习内核的四步法则,思维导图的设计尤为团清重要,这也是能否学习好内核的关键
5.语言基础也需要扎实,所以需要把C语言巩固巩固
在linux上怎样增加一个i2c设备?
假设手上有一块从淘宝上买来的开发板,我要在开发板的I2C总线上增加一个从设备(如at24c08),那么我要怎样写这晌答个“I2C设备驱动”,让
应用程序可以访问at24c08呢?
先来看一个最简单的i2c设备驱动:
static struct i2c_board_info at24cxx_info = { //所支持的i2c设备的列表
I2C_BOARD_INFO(“at24c08”, 0x50), //一项代表一个支持的设备,它的名字叫做“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);
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内核i2c子系统驱动的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于linux内核i2c子系统驱动,Linux内核i2c子系统驱动介绍,求教怎么学习linux内核驱动,在linux上怎样增加一个i2c设备?的信息别忘了在本站进行查找喔。
香港服务器首选树叶云,2H2G首月10元开通。树叶云(shuyeidc.com)提供简单好用,价格厚道的香港/美国云服务器和独立服务器。IDC+ISP+ICP资质。ARIN和APNIC会员。成熟技术团队15年行业经验。
linux 的i2c配置时,关于i2c_client的flag是什么意思?
i2c是master和client架构,master就是主控制器这边的驱动,client就是设备这边的驱动,master一般都写好了,你只需要写相应的client驱动,也就是设备驱动,然后在板级文件里面注册一个设备。 就可以啦。
学习ARM&LINUX嵌入式系统,需要哪些服务软件,详细介绍一下各种软件的功能和特点。
1、Linux 基础安装Linux操作系统 Linux文件系统 Linux常用命令 Linux启动过程详解。 2、Shell 编程基础Shell简介 认识后台程序Bash编程熟悉Linux系统下的编辑环境。 3、Linux 下的 C 编程基础linux C语言环境概述 Gcc使用方法 Gdb调试技术。 4、嵌入式系统开发基础嵌入式系统概述 交叉编译 配置TFTP服务 配置NFS服务 下载Bootloader和内核 嵌入式Linux应用软件开发。 4、嵌入式系统移植Linux内核代码 平台相关代码分析 ARM平台介绍 平台移植的关键技术 移植Linux内核到 ARM平台 了解移植的概念 能够移植Linux内核移植Linux2.6内核到 ARM9开发板。 5、嵌入式 Linux 下串口通信串行I/O的基本概念 嵌入式Linux应用软件开发流程 Linux系统的文件和设备。 6、嵌入式系统中多进程程序设计Linux系统进程概述 嵌入式系统的进程特点 进程操作 守护进程 相关的系统调用了解Linux系统中进程的概念。 ...网上很多~可以先从虚拟机玩起。 A.一般安装一个VMWARE虚拟机,再从网上下载个RedHat9.0的光盘镜像。 这个比较适合入门linux,当然也有Cygwin的,不过不推荐。 B.然后就可以按照上面的步骤学起来了,等把linux的shell和gcc,gdb,系统编程,gui(QT,miniGUI,MicroWin等等)玩好之后,可以买个开发板了,这里就不说明具体品牌了,2410/2440开发板很多的。 C.然后开始玩开发板,常用的代码编辑工具有:SourceInsight,UE。 还有代码比较工具,BeyondCompare。 当然还有ADS1.2,这个是必不可少的,可以先把ARM开发板当单片机开发板玩!先熟悉具体硬件设备的使用,如UART,SPI,LCD控制器等,最后再去玩Bootloader,系统移植,内核,文件系统,应用编程,驱动编程。 。 。
嵌入式开发入门--系统学习方案
嵌入式系统开发学习--从入门到精通 很多新手学习嵌入式系统,不清楚那么多方向舵知识和参考书,该从哪里开始学习。 入手了,却又在该先学习什么后学习什么上失去方向。 这里有你想要的答案,帮你指点迷经。 这是我在ITjob培训网上找到的课程大纲,觉得作为嵌入式系统开发的学习步骤,按部就班地去施行和学习,到不失为一种好的学习方法:)就算是作为参考也是有很好的价值的! 随着现代社会信息化进程的加快,嵌入式系统被广泛的地应用于军事、家用、工业、商业、办公、医疗等社会各个方面,表现出很强的投资价值。 从国际范围来看,作为数字化电子信息产品核心的嵌入式系统目前其硬件和软件开发工具市场已经突破2000亿美元,嵌入式系统带来的全球工业年产值更是达到了一万亿美元,随着全球经济的持续增长以及信息化的加速发展,嵌入式系统市场必将进一步增长。 本课程是为了适应目前发展迅速的嵌入式Linux需求而设计,课程目标是让学员达到适应嵌入式应用软件开发、嵌入式系统开发或嵌入式驱动开发的基本素质。 课程循序渐进的带领您嵌入式开发的世界,采用了目前应用最广泛的软硬件开发平台(Linux和Arm),可以保证您尽量贴近目前企业需求。 学习步骤如下:(一步步来哦:) 1、Linux 基础 安装Linux操作系统 Linux文件系统 Linux常用命令 Linux启动过程详解 熟悉Linux服务能够独立安装Linux操作系统 能够熟练使用Linux系统的基本命令 认识Linux系统的常用服务安装Linux操作系统 Linux基本命令实践 设置Linux环境变量 定制Linux的服务 Shell 编程基础使用vi编辑文件 使用Emacs编辑文件 使用其他编辑器 2、Shell 编程基础 Shell简介 认识后台程序 Bash编程熟悉Linux系统下的编辑环境 熟悉Linux下的各种Shell 熟练进行shell编程熟悉vi基本操作 熟悉Emacs的基本操作 比较不同shell的区别 编写一个测试服务器是否连通的shell脚本程序 编写一个查看进程是否存在的shell脚本程序 编写一个带有循环语句的shell脚本程序 3、Linux 下的 C 编程基础 linux C语言环境概述 Gcc使用方法 Gdb调试技术 Autoconf Automake Makefile 代码优化 熟悉Linux系统下的开发环境 熟悉Gcc编译器 熟悉Makefile规则编写Hello,World程序 使用 make命令编译程序 编写带有一个循环的程序 调试一个有问题的程序 4、嵌入式系统开发基础 嵌入式系统概述 交叉编译 配置TFTP服务 配置NFS服务 下载Bootloader和内核 嵌入式Linux应用软件开发流程 熟悉嵌入式系统概念以及开发流程 建立嵌入式系统开发环境制作cross_gcc工具链 编译并下载U-boot 编译并下载Linux内核 编译并下载Linux应用程序 5、嵌入式系统移植 Linux内核代码 平台相关代码分析 ARM平台介绍 平台移植的关键技术 移植Linux内核到 ARM平台 了解移植的概念 能够移植Linux内核移植Linux2.6内核到 ARM9开发板 6、嵌入式 Linux 下串口通信 串行I/O的基本概念 嵌入式Linux应用软件开发流程 Linux系统的文件和设备 与文件相关的系统调用 配置超级终端和MiniCOM 能够熟悉进行串口通信 熟悉文件I/O 编写串口通信程序 编写多串口通信程序 7、嵌入式系统中多进程程序设计 Linux系统进程概述 嵌入式系统的进程特点 进程操作 守护进程 相关的系统调用了解Linux系统中进程的概念 能够编写多进程程序编写多进程程序 编写一个守护进程程序 sleep系统调用任务管理、同步与通信 Linux任务概述 任务调度 管道 信号 共享内存 任务管理 API 了解Linux系统任务管理机制 熟悉进程间通信的几种方式 熟悉嵌入式Linux中的任务间同步与通信 编写一个简单的管道程序实现文件传输 编写一个使用共享内存的程序
发表评论