linux为何使用设备树,Linux为什么要引入设备树

ARM Linux社区为什么要引入设备树

Linux之父Linus Torvalds闲来无事,在翻看ARM Linux代码的时候,有一天终于忍不住了。他在2011年3月17日的ARM Linux邮件列表中说道:“This whole ARM thing is a f*cking pain in the ass”。这句话迫使ARM Linux社区引入了设备树。

Linus Torvalds为什么会发飙呢?而ARM Linux社区的牛人为什么又乖乖地听话了?你得首先理解Linux设备驱动框架中一个非常好的设计:设备信息和驱动分离。

为了什么说明设备信息和驱动分离的概念,先来看一个简单的模拟代码实例:

【例-1】实现一个代码,把要使用的信息简单写死在代码中:

int add() /*模拟驱动代码*/

{

return 3+5; /*模拟设备信息*/

}

优点:简单

缺点:一旦加数和被加数发生变化就得改代码

改进设计如下:

【例-2】实现一个代码,把要使用的信息和操作代码分离开来:

struct dev{

int id;

int x;

int y;

}; /*模拟设备信息结构*/

strcut drv{

int id;

int (*add)(struct dev *info);

}; /*模拟驱动结构*/

int add(struct dev *info) /*模拟驱动代码*/

{

return info->x + info->y; /*模拟设备信息-通过参数传递进来*/

}

struct drv drv = {

.id = 1,

.add = add,

};

/*模拟设备信息*/

struct dev dev = {

.id = 1,

.x = 3,

.y = 5,

};

/*模拟总线初始化匹配设备信息和驱动代码*/

int bus()

{

if(dev.id == drv.id){

return drv.add(&dev);

}

...

}

优点:不管加数和被加数怎么变化,不需要修改代码,仅需要修改信息

缺点:结构比较复杂

那这个设备信息和驱动分离的设计跟驱动有什么关系呢?熟悉硬件编程的同学都知道,硬件一般的构成可以使用下图简单表述:

a43f6f11e2f650f9f70650e2a00a6747.png

操作外设的驱动代码逻辑,只要硬件是一样的,就不会变化。但是外设挂到不同的主机上,可能会存在I/O地址的变化,如果有中断也是一样的,中断号也可能不同。这些I/O地址和中断号就是设备信息,使用这些信息来操作控制硬件的代码就是驱动。

如果采用【例-1】的设计方式,那么同一个硬件外设接到不同的主机,或是换了地址线/中断线,设备信息就变化了,得去修改驱动。但是采用【例-2】的方式进行设计,问题就迎刃而解:不管同样的外设硬件接到哪里或是那个平台,其驱动代码逻辑并不需要改动,而仅仅需要改变下设备信息,主要的就是I/O地址和中断号。

说了这么半天,跟引入设备树有什么关系呢?华清教学使用的开发板(A8/A9)都使用DM9000网卡芯片。DM9000驱动是开源的,在主线内核源码中就有。我们每次基于A8/A9板子移植的时候,DM9000驱动并没有修改过,仅仅是选配了下,主要的工作是在板级文件中添加了设备信息。DM9000驱动使用的是platform框架,所以添加了一份DM9000网卡芯片的platform_device信息。问题来了,如果使用C代码的形式来描述设备信息,则在内核源码中,将会有多份DM9000的platform_device设备信息,造成了内核代码冗余。

解决这个问题的办法就是引入设备树,改造【例-2】来说明设备树的作用。

【例-3】实现一个代码,不仅把要使用的信息和操作代码分离开来,而且信息不是C代码编写的,而是文本配置文件保存的:

struct dev{

int id;

int x;

int y;

}; /*模拟设备信息结构*/

strcut drv{

int id;

int (*add)(struct dev *info);

}; /*模拟驱动结构*/

int add(struct dev *info) /*模拟驱动代码*/

{

return info->x + info->y; /*模拟设备信息-通过参数传递进来*/

}

struct drv drv = {

.id = 1,

.add = add,

};

/*模拟设备树-一个特殊的配置文件,xxx.dtbs的文本文件*/

/{

......

Dm9000{

x = 3;

y = 5;

};

......

};

/*模拟总线初始化匹配设备信息和驱动代码*/

int bus()

{

/*模拟设备树初始化处理*/

读文件(xxx.dtbs);

解析文件内容(根据设备树的规则来解析);

生成struct dev设备信息;

if(dev.id == drv.id){

return drv.add(&dev);

}

...

}

如果像【例-3】这样,就可以解决大量设备信息的代码冗余问题。

推而广之,系统的软硬件信息都可以使用设备树来描述。这样的话,ARM Linux社区就不会因为支持板子和驱动越来越多造成内核源码中出现很多冗余代码(主要是板级文件),仅仅需要移植者,把系统的软硬件信息通过设备树提供出来,选配一下内核代码,就可以了。

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
设备树(device tree)机制是Linux内核从linux-3.x版本开始引进的一种机制,目的是解决内核源码的arch/arm目录下代码混乱的问题:随着ARM生态的快速发展,在内核源码的arch/arm目录下,存放着几十种arm芯片和几百个开发板相关的源文件,很多开发板和处理器的中断、寄存器等相关硬件资源都在这个目录下以.c或.h的文件格式定义。而对于内核来说,与这些硬件耦合,会导致内核代码混乱不堪,每个开发板上运行的内核镜像都必须单独编译配置,无法通用。什么时候Linux内核能像Windows镜像那样,无论你的电脑什么配置,一个Windows安装包,都可以直接下载安装运行呢?设备树机制,实现了Linux内核和硬件平台的解耦:每个硬件平台的硬件资源使用一个设备树文件(xxx.dts)来描述,而不是在arch/arm下以.c 或 .h 文件来定义。Linux内核是一个通用的内核,在启动过程中,在通过解析设备树中的硬件资源来初始化某个具体的平台。 引入设备树后,很多和内核驱动开发的工作也发生了变化:以往驱动工程师关注的头文件宏定义、寄存器定义,现在这些基本上不用关注,关注的重点则转向了如何根据硬件平台去配置和修改设备树文件。很多驱动的编程接口也发生了变化,开始慢慢使用device tree提供的编程接口去开发驱动。本期课程主要面向嵌入式开发人员,分享Linux下驱动开发所需要的设备树知识和必备技能

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值