0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

简单地学习一下设备树的一些知识

倩倩 来源:一口Linux 作者:一口Linux 2022-09-09 15:29 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群


	

在platform_device部分有简单说明描述设备有两种方法:一种是使用platform_device结构体来指定;另一种是使用设备树来描述。

本篇笔记我们就来简单地学习一下设备树的一些知识。

什么是设备树

a676b120-2fcf-11ed-ba43-dac502259ad0.png

设备树简单理解就是描述设备信息(资源)的一棵树。设备树(Device Tree)用代码体现如下:

a682d180-2fcf-11ed-ba43-dac502259ad0.png

这些代码被保存在.dts/dtsi后缀文件中,也即设备树源文件 DTS(DeviceTree Source)。

这些源文件同我们的C代码一样,并不能直接使用的,而是得经过一个编译过程生成机器可运行的二进制文件,如:

a68f9168-2fcf-11ed-ba43-dac502259ad0.png

dts文件使用dtc工具编译生成dtb文件,这个dtb文件就是内核可以使用的文件。例如我们的板子跑起来之后,我们系统使用的设备树文件就存在目录/boot下:

a69b3b12-2fcf-11ed-ba43-dac502259ad0.png

Linux为什么会引入设备树?

在上一个实验:【Linux笔记】LED驱动实验(总线设备驱动模型)中我们使用了platform_device结构体来描述led设备(硬件资源)。既然已经有了描述设备的方法了,为什么还要引入设备树呢?

因为Linux内核中有很多BSP(板级支持包),不同的BSP会包含着不同的描述设备的代码(.c或.h文件)。

随着芯片的发展,Linux内核中就包含着越来越多这些描述设备的代码,导致Linux内核代码会很臃肿。

这导致Linux之父Linus 大发雷霆:"this whole ARM thing is a f*cking pain in the ass"。

因此引入了设备树文件,从而可精简一些臃肿的C代码。除此之外,.dts编译生成.dtb文件的过程要比.c编译生成驱动模块、加载驱动模块的过程要简单很多,也更方便我们进行开发。

设备树的语法

设备树源文件也是需要根据一定规则来编写的,同C语言一样,也要遵循一些语法规则。下面简单看一下设备树的源码结构及语法。

先看一个设备树示例:

a6b00128-2fcf-11ed-ba43-dac502259ad0.png

1、节点格式

label:node-name@unit-address

其中:

label:标号

node-name:节点名字

unit-address:单元地址

label 是标号,可以省略。label 的作用是为了方便地引用 node。比如:

a6bccfde-2fcf-11ed-ba43-dac502259ad0.png

可以使用下面 2 种方法来修改 uart@fe001000 这个 node:

a6cc16ce-2fcf-11ed-ba43-dac502259ad0.png

2、属性格式 简单地说, properties 就是“name=value”, value 有多种取值方式。示例:

  • 一个32位的数据,用尖括号包围起来,如

interrupts=<170xc>;

  • 一个64位数据(使用2个32位数据表示),用尖括号包围起来,如:

clock-frequency=<0x000000010x00000000>;

  • 有结束符的字符串,用双引号包围起来,如:

compatible="simple-bus";

  • 字节序列,用中括号包围起来,如:

local-mac-address=[000012345678];//每个byte使用2个16进制数来表示
local-mac-address=[000012345678];//每个byte使用2个16进制数来表示

  • 可以是各种值的组合,用逗号隔开,如:

compatible="ns16550","ns8250";
example=<0xf00f000019>,"astrangepropertyformat";

3、一些标准属性(1) compatible 属性

“compatible”表示“兼容”,对于某个LED,内核中可能有A、B、C三个驱动都支持它,那可以这样写:

led{
compatible=“A”,“B”,“C”;
};

内核启动时,就会为这个LED按这样的优先顺序为它找到驱动程序:A、B、C。

(2)model 属性

model属性与compatible属性有些类似,但是有差别。compatible属性是一个字符串列表,表示可以你的硬件兼容A、B、C等驱动;model用来准确地定义这个硬件是什么。

比如根节点中可以这样写:

/{
compatible="samsung,smdk2440","samsung,mini2440";
model="jz2440_v3";
};

它表示这个单板,可以兼容内核中的“smdk2440”,也兼容“mini2440”。

从compatible属性中可以知道它兼容哪些板,但是它到底是什么板?用model属性来明确。

(3)status 属性

status 属性看名字就知道是和设备状态有关的, status 属性值也是字符串,字符串是设备的状态信息,可选的状态如下所示:

a6d98a0c-2fcf-11ed-ba43-dac502259ad0.png

(4)#address-cells 和#size-cells 属性

格式:

address-cells:address要用多少个32位数来表示;
size-cells:size要用多少个32位数来表示。

比如一段内存,怎么描述它的起始地址和大小?

下例中,address-cells为1,所以reg中用1个数来表示地址,即用0x80000000来表示地址;size-cells为1,所以reg中用1个数来表示大小,即用0x20000000表示大小:

/{
#address-cells=<1>;
#size-cells=<1>;
memory{
reg=<0x800000000x20000000>;
};
};

(5)reg 属性

reg属性的值,是一系列的“address size”,用多少个32位的数来表示address和size,由其父节点的# address-cells、#size-cells决定。示例:

/dts-v1/;
/{
#address-cells=<1>;
#size-cells=<1>;
memory{
reg=<0x800000000x20000000>;
};
};

(7)name 属性

过时了,建议不用。它的值是字符串,用来表示节点的名字。在跟platform_driver匹配时,优先级最低。compatible属性在匹配过程中,优先级最高。

(8)device_type 属性

过时了,建议不用。它的值是字符串,用来表示节点的类型。在跟platform_driver匹配时,优先级为中。compatible属性在匹配过程中,优先级最高。

3、常用的节点(1)根节点

用 / 标识根节点,如:

/dts-v1/;
/{
model="SMDK24440";
compatible="samsung,smdk2440";

#address-cells=<1>;
#size-cells=<1>;
};

(2)CPU节点

一般不需要我们设置,在 dtsi 文件中都定义好了,如:

cpus{
#address-cells=<1>;
#size-cells=<0>;

cpu0:cpu@0{
.......
}
};

(3)memory 节点

芯片厂家不可能事先确定你的板子使用多大的内存,所以 memory 节点需要板厂设置,比如:

memory{
reg=<0x800000000x20000000>;
};

(4)chosen 节点

我们可以通过设备树文件给内核传入一些参数,这要在chosen节点中设置bootargs属性:

chosen{
bootargs="noinitrdroot=/dev/mtdblock4rwinit=/linuxrcconsole=ttySAC0,115200";
};

操作设备树的函数

Linux 内核给我们提供了一系列的函数来获取设备树中的节点或者属性信息,这一系列的函数都有一个统一的前缀“of_”(“open firmware”即开放固件。),所以在很多资料里面也被叫做 OF 函数。

1、节点相关操作函数 Linux 内核使用 device_node 结构体来描述一个节点,此结构体定义在文件 include/linux/of.h 中,定义如下:

a6f4f274-2fcf-11ed-ba43-dac502259ad0.png

与查找节点有关的 OF 函数有 5 个:

(1) of_find_node_by_name 函数

of_find_node_by_name 函数通过节点名字查找指定的节点,函数原型如下:

structdevice_node*of_find_node_by_name(structdevice_node*from,
constchar*name);

(2) of_find_node_by_type 函数

of_find_node_by_type 函数通过 device_type 属性查找指定的节点,函数原型如下:

structdevice_node*of_find_node_by_type(structdevice_node*from,constchar*type);

(3) of_find_compatible_node 函数

of_find_compatible_node 函数根据 device_type 和 compatible 这两个属性查找指定的节点,函数原型如下:

structdevice_node*of_find_compatible_node(structdevice_node*from,constchar*type,
constchar*compatible);

(4)of_find_matching_node_and_match 函数

of_find_matching_node_and_match 函数通过 of_device_id 匹配表来查找指定的节点,函数原型如下:

structdevice_node*of_find_matching_node_and_match(structdevice_node*from,conststructof_device_id*matches,conststructof_device_id**match);

(5)of_find_node_by_path 函数

of_find_node_by_path 函数通过路径来查找指定的节点,函数原型如下:

inlinestructdevice_node*of_find_node_by_path(constchar*path);

2、提取属性值的 OF 函数 Linux 内核中使用结构体 property 表示属性,此结构体同样定义在文件 include/linux/of.h 中,内容如下:

a7036b42-2fcf-11ed-ba43-dac502259ad0.png

Linux 内核也提供了提取属性值的 OF 函数 :(1) of_find_property 函数

of_find_property 函数用于查找指定的属性,函数原型如下:

property*of_find_property(conststructdevice_node*np,constchar*name,int*lenp);

(2)of_property_count_elems_of_size 函数

of_property_count_elems_of_size 函数用于获取属性中元素的数量,比如 reg 属性值是一个数组,那么使用此函数可以获取到这个数组的大小,此函数原型如下:

intof_property_count_elems_of_size(conststructdevice_node*np,constchar*propname,intelem_size);

(3)读取 u8、 u16、 u32 和 u64 类型的数组数据

a713b09c-2fcf-11ed-ba43-dac502259ad0.png

(4)读取 u8、 u16、 u32 和 u64 类型属性值

a735718c-2fcf-11ed-ba43-dac502259ad0.png

(5)of_property_read_string 函数

of_property_read_string 函数用于读取属性中字符串值,函数原型如下:

intof_property_read_string(structdevice_node*np,constchar*propname,constchar**out_string)

审核编辑 :李倩


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Linux
    +关注

    关注

    88

    文章

    11628

    浏览量

    217959
  • 代码
    +关注

    关注

    30

    文章

    4941

    浏览量

    73140
  • 设备树
    +关注

    关注

    0

    文章

    40

    浏览量

    3527

原文标题:整理了一份Linux设备树基础知识,建议收藏!

文章出处:【微信号:良许Linux,微信公众号:良许Linux】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    贴片电容精度J±5%的一些详细知识

    贴片电容精度J±5%表示电容的实际值与标称值之间的偏差范围在±5%以内 ,以下是关于贴片电容精度J±5%的一些详细知识、精度等级含义 J±5% :字母“J”在贴片电容的标识中通常表示标称精度
    的头像 发表于 11-20 14:38 134次阅读
    贴片电容精度J±5%的<b class='flag-5'>一些</b>详细<b class='flag-5'>知识</b>

    国民技术MCU芯片护航支付宝碰一下设备创新

    近日,全球顶尖金融科技盛会Money20/20公布首届创新大奖The Money Awards结果,“支付宝碰一下”从众多参赛企业中脱颖而出,凭借创新的解决方案和极致的用户体验摘得“支付”类别大奖,成为该类别中唯的中国企业。
    的头像 发表于 11-06 10:15 806次阅读

    ARM入门学习方法分享

    的关键。旦你掌握了ARM的基本概念和汇编语言,你可以开始进行一些简单的ARM项目。你可以尝试编写一些简单的程序,如LED闪烁、按键输入等,
    发表于 07-23 10:21

    极海APM32F407 uc/os3学习笔记之任务管理介绍

    最近了解了uc/os3这个操作系统,上篇介绍了uc/os3如何正确移植到APM32F407开发板上,根据我最近学到的一些知识,这篇文章主要介绍一下uc/os3中的一些
    的头像 发表于 05-24 14:37 797次阅读
    极海APM32F407 uc/os3<b class='flag-5'>学习</b>笔记之任务管理介绍

    Debian和Ubuntu哪个好一些

    兼容性对比Debian和Ubuntu哪个好一些,并为您揭示如何通过RAKsmart服务器释放Linux系统的最大潜能。
    的头像 发表于 05-07 10:58 852次阅读

    收藏的一些库存,直流无刷技术+源码+论文(建议打包)

    这也是我网络上淘过来收藏的一些资料,免费跟大家起分享一下,建议下载哦,收藏不易
    发表于 03-17 20:17

    请问stm32mp257如何修改设备并加载驱动?

    1、重新编译kernel容易报错,重新编译设备也会报错。 2、加载驱动,编译环境应该对应,加载不成功。 3、想知道整体比方说,修改下IO,修改下设备,加入
    发表于 03-07 08:05

    如何构建次充电可以运行数月的嵌入式设备

    想象一下设个宠物GPS追踪器,它需要跟踪时间、安排任务和节约电力,但保持MCU和GPS全天候活跃将消耗数小时的电池。 你如何解决这个问题? • 仅在必要时使用RTC唤醒MCU。 • 使用系统
    的头像 发表于 03-04 11:25 644次阅读
    如何构建<b class='flag-5'>一</b>个<b class='flag-5'>一</b>次充电可以运行数月的嵌入式<b class='flag-5'>设备</b>?

    求解答,设备问题

    请问,rk3588j要再提取个USB3.0接口设备怎么改
    发表于 02-20 11:22

    为什么你的串口总是丢一些特殊字符?

    导读在嵌入式开发和物联网应用中,Linux系统的串口通信至关重要。本文将简单介绍Linux串口设备的命名规则和termios结构体,并解析终端的三种工作模式,帮助开发者更好地掌握Linux串口编程
    的头像 发表于 02-06 13:26 618次阅读
    为什么你的串口总是丢<b class='flag-5'>一些</b>特殊字符?

    科技在物联网方面

    科技在物联网领域有多方面的涉及和发展,以下是一些具体信息: 传感器技术合作 与传感器公司合作:宇科技与一些传感器技术公司有合作,例如奥比中光为宇
    发表于 02-04 06:48

    嵌入式学习-飞凌嵌入式ElfBoard ELF 1板卡-初识设备设备组成和结构

    前边讲解了内核编译选项的配置,这节我们详细讲一下设备设备知识是Linux驱动开发人员必
    发表于 01-08 08:32

    飞凌嵌入式ElfBoard ELF 1板卡-初识设备设备组成和结构

    前边讲解了内核编译选项的配置,这节我们详细讲一下设备设备知识是Linux驱动开发人员必
    发表于 01-07 09:16

    “碰一下”支付背后的4G技术

    不知道你是否有留意,近期,在线下支付场景中,多了个支付宝“碰一下”支付的设备,只需要“解锁手机—碰一下—确认”即可完成支付,对比打开付款码支付,步骤确实更加简洁。
    的头像 发表于 01-03 16:27 4997次阅读

    FOC电路学习路上的一些硬件坑

    记录一下驱动直流无刷电机走过的坑。我是和是室友起在玩FOC,电路方面也是借鉴了他的。我俩共同的个心得就是,电路这个东西直接抄要么你就要原封不动的复刻下来,要么你就要搞懂电路中的每个电阻电容都起到
    的头像 发表于 12-07 10:14 1800次阅读
    FOC电路<b class='flag-5'>学习</b>路上的<b class='flag-5'>一些</b>硬件坑