深入探索:Linux下驱动设备树接口 (linux驱动设备树接口)

随着嵌入式设备的普及,Linux系统在这一领域的应用也愈发广泛。而在Linux系统中,驱动设备树接口成为了嵌入式设备驱动的重要组成部分,广泛应用于包括嵌入式系统、嵌入式ARM开发板等在内的硬件设备领域。本文将从驱动设备树接口的基础概念入手,深入探究其在Linux系统中的应用与优势。

一、驱动设备树接口的基础概念

在介绍驱动设备树接口之前,我们先来了解一下设备树。设备树是一种基于树形结构的硬件平台描述语言,它可以用来描述硬件平台上各种设备的物理信息,如设备的名称、地址、中断等。设备树的主要作用是解决设备资源配置的问题,可以方便地将设备信息传递给内核,从而完成设备的初始化工作。

而驱动设备树接口(Driver Device Tree,简称DDT)则是Linux内核中实现设备树机制的接口。通过驱动设备树接口,内核可以获取设备信息,并根据设备树的描述来初始化相应的驱动程序。驱动设备树接口是一种通用的接口,应用广泛,包括但不限于嵌入式设备、开发板、服务器等领域。

二、驱动设备树接口的应用

驱动设备树接口的主要作用是为驱动程序提供设备信息,从而完成设备的初始化。而驱动设备树接口的使用方法,可以分为驱动程序对设备树信息的解析和设备树的编写两部分。

1、设备树信息的解析

驱动程序使用驱动设备树接口的之一步,就是解析设备树中的信息。设备树中包含了许多设备的物理信息,如设备名、中断号、地址等,通过解析设备树,驱动程序可以从中获取需要的信息,从而完成相应的初始化工作。

以常见的I2C总线为例,其设备树节点的基本格式如下:

“`

i2c@address {

compatible = “i2c-device-name”;

reg =

;

interrupt-parent = &gpio;

interrupts = ;

};

“`

在此,驱动程序首先需要调用of_match_device()函数,将设备树节点与驱动程序的匹配表进行匹配。如果匹配成功,程序则会进入到of_platform_populate()函数中,开始初始化相应的驱动程序。

2、设备树的编写

设备树的编写,是驱动程序开发的重要组成部分。在编写设备树时,开发人员需要遵循一系列规范,以便内核能够正确地解析设备树。下面我们来介绍一下设备树的编写规范。

(1)设备树节点的名称

在设备树中,每个节点都必须要有一个独一无二的名称。节点名称一般遵循以下规范:

“`

device@physical_address {

};

“`

还可以使用以下格式:

“`

device@physical_address {

compatible = “device-model”;

};

“`

其中,device为设备名称,physical_address为设备的物理地址,compatible表示设备的模块。

(2)设备树节点的类型

在设备树中,每个节点都必须要有一个类型。节点类型一般遵循以下规范:

“`

device {

compatible = “device-model”;

};

“`

其中,device表示设备的类型,compatible表示设备的模块。

(3)设备树节点的属性

在设备树中,还可以为每个节点添加一些属性。这些属性一般遵循以下规范:

“`

device {

compatible = “device-model”;

reg = ;

};

“`

其中,reg表示设备的内存地址信息。

三、驱动设备树接口的优势

驱动设备树接口作为嵌入式设备驱动的重要组成部分,具有以下优势:

1、对于嵌入式系统来说,设备树可以直接描述芯片的硬件结构,便于物理硬件的描述和修改。

2、设备树可以提供与硬件平台相关的信息,方便内核驱动程序对硬件进行初始化。

3、对于不同人开发的硬件,设备树可以起到统一的作用,从而方便外围设备的扩展。

4、通过使用设备树,内核不再需要硬编码来实现硬件初始化,因此可以更加方便、快捷、简单地实现驱动程序的开发。

相关问题拓展阅读:

linux下如何开发sdio设备驱动?

以LinuxKernelSdioMx28 / LinuxKernelSdioMx53项目代码为例:

– module_init(DibBridgeTargetModuleInit)

驱动模块初始化入口

– DibBridgeTargetModuleInit():模块初始化函数。

1.调用sdio_register_driver()注册sdio接口驱动,

2.调用register_chrdev()注册驱动模块为字符设备。

– sdio_register_driver():向系统注册sdio接口驱动,调用以后,系统会触发sdio设备id检测,如果设备id和接口驱动里.id_table里定迅耐义的id一致,则系统调用probe函数。

1. 可以在DibBridgeTargetModuleInit()里调用,这样inod之后,驱动接口即被注册(设备id被注册),有相应设备插入则probe会被调用(此种做法参考LinuxKernelSdioMx28)

2. 也可以在sdio初始化时调用,这样设备插入时,probe不会被调用,只有在sdio初始化,sdio_register_driver()被调用时,系统才会重新检测设备id,并调用probe。(此种做法好处是,模块初始化不涉及何种设备,具有更好的通用性。参考LinuxKernelSdioMx53)

– static struct sdio_driver Dib_sdio_driver

是键游sdio接口驱动的结构体,包括.id_table, .probe()函数等,如下

static struct sdio_driver Dib_sdio_driver = {

.name = “Dib_sdio”,

.id_table = Dib_sdio_ids,

.probe = Dib_sdio_probe,

.remove = __devexit_p(Dib_sdio_remove),

};

其中.id_table很重要,它里面定义了此sdio驱动模块关心的sdio设备id号,只有插入的sdio设备的id号和这里面定义的id对应上,系统才会调用.probe函数。

– register_chrdev()

将驱动模块向系统注册为字符设备,并将操作该设备的接口函数file_operations也一起注册了。

1.可以在DibBridgeTargetModuleInit()里调用。(参考LinuxKernelSdioMx53/LinuxKernelSdioMx28代码)

2.也可以在probe函数里调用,即只有在系统稿昌销检测到硬件设备时才去注册字符设备(参考sdk8remote代码)

– struct file_operations

包含如下最基本的文件操作函数,

struct file_operations fops =

{

.ioctl = DibBridgeTargetModuleIoctl, //控制命令传输或数据传输

.open = DibBridgeTargetModuleOpen,

.read = DibBridgeTargetModuleReadData,//数据传输

.write = DibBridgeTargetModuleWriteData

.release = DibBridgeTargetModuleRelease,

};

– .ioctl/.read 等等

user space和kernel space的传输通道,通过使用copy_from_user和copy_to_user这样的函数来实现数据传递

Linux方面的想相关知识可以百度搜索《Linux就该这么学》进行学习了解

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= 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_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 = {

.sda_pin = 1dev.platform_data=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, 2)) != 2) {

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

return -EIO;

}

关于linux驱动设备树接口的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。


数据运维技术 » 深入探索:Linux下驱动设备树接口 (linux驱动设备树接口)