Linux驱动(五)设备树

news2024/9/27 3:11:37

1、前言

设备树是一种描述硬件平台和设备的数据结构,它以一种结构化的方式描述了系统中的各种设备和资源,包括处理器、内存、外设和总线等。设备树通常用于嵌入式系统和嵌入式 Linux 系统中,它可以帮助操作系统内核在启动时自动识别硬件,并正确配置驱动程序和资源。

使用设备树的主要原因是为了解决硬件平台的多样性和复杂性。在嵌入式系统中,不同的硬件平台可能有不同的设备和资源配置,使用设备树可以使操作系统内核在不同的硬件平台上运行,而无需修改内核代码。比如在之前讲解的platform驱动模型中,device实现的设备节点的数据内容可以通过设备树节点转换得到,这样可以大大简化软件开发和维护工作,同时也提高了代码的可移植性和可重用性。

设备树官网:https://www.devicetree.org

2、DTS文件

2.1 文件布局

官方文档中提供的文件布局示例如下,其中“/dts-v1/;”表示使用版本;“[memory reservations]”为可选设置,表示设置预留内存;“/”表示根节点;“[property definitions]”表示属性定义;“[child nodes]”表示子节点:

/dts-v1/;
[memory reservations]
  / {
  [property definitions]
  [child nodes]
  };

一个简单的示例如下:

/dts-v1/;  // 设备树版本声明

/ {
    #address-cells = <1>;  // 设备地址的单元数量
    #size-cells = <1>;  // 设备大小的单元数量
    compatible = "virtual,machine";  // 设备兼容性描述

    memory {
        device_type = "memory";  // 设备类型描述
        reg = <0x00000000 0x40000000>; // 1GB内存,起始地址为0x00000000
    };

    cpus {
        #address-cells = <1>;  // 设备地址的单元数量
        #size-cells = <0>;  // 设备大小的单元数量
        cpu@0 {
            compatible = "virtual,cpu";  // 设备兼容性描述
            reg = <0>;  // 寄存器地址
            status = "okay";  // 设备状态描述
        };
    };
};
2.2 属性格式

属性有两种格式:

[label:] property-name = value;
[label:] property-name;

其中value的取值有三种,以定义为一个由32位整数单元格组成的数组、以空结尾的字符串、字节字符串或它们的组合,以下为示例:

// 32位整数(常用)
assigned-clocks = <0x6>;
reg = <0x0 0x6520000 0x0 0x100 0x0 0x6524000 0x0 0x3fc>;

// 字符串(常用)
compatible = "allwinner,pll-clock";
lock-mode = "new";

// 字节序列(少见) 每个字节必须使用两个16进制数字表示 比如1要写成01 中间空格可省略
flash0_flvdd = [0011];

// 组合方式(少见)
pinctrl = "active", "sleep", <0x1>;
2.3 节点格式

对象节点用节点名称和单位地址定义,用大括号标记节点定义的开始和结束,在它们之前可能会有一个标签(非必选),其一般格式如下:

[label:] node-name[@unit-address] {
    [properties definitions]
    [child nodes]
};

节点可以包含属性定义和子节点定义,如果两者都存在,属性应该放在子节点之前。

3、实例分析

3.1 常见属性

(1)compatible

根节点下兼容的属性值由一个或多个为设备定义特定编程模型的字符串组成。此字符串列表应该被客户端程序用于选择设备驱动程序,香橙派的设备树文件中指定如下,一个操作系统系统将首先尝试找到一个支持allwinner,h616的设备驱动程序,如果没有的话会即继续往后查找"arm,sun50iw9p1"。

compatible = "allwinner,h616", "arm,sun50iw9p1";

(2)model

根节点下模型属性值是一个<字符串>,它指定了设备的制造商型号。推荐的格式是:“制造商,型号”,其中制造商是描述制造商名称的字符串,型号指定型号,作用和compatible类似:

model = "Orange Pi Zero 2";

(3)phandle

phandle属性为设备树中唯一的节点指定一个数字标识符。phandle属性值用于需要引用与该属性关联的节点的其他节点。其使用示例如下:

pic@10000000 {
    phandle = <1>;
    interrupt-controller;
    reg = <0x10000000 0x100>;
};
// 引用上述节点
another-device-node {
    interrupt-parent = <1>;
};

(4)status

状态属性表示设备的运行状态,一般取值如下:

"okay"
指示设备可运行
"disabled"
表示设备目前未运行,但可能在将来运行(例如,没有插入或关闭)
"reserved"
表示该设备已运行,但不应使用,通常用于由另一个软件组件控制的设备,如平台固件
"fail"
表示该设备无法运行。在设备中检测到严重的错误,不能运行
"fail-sss"
表示该设备无法运行。在设备中检测到严重的错误,不能运行,该值的sss部分是特定于该设备的,并指示所检测到的错误条件

(5)#address-cells 和#size-cells

address-cells和size-cells表示的是元素所处的当前节点的子节点中表示内存地址和大小锁占用多少个32位的数据。示例如下,soc节点的#地址单元格和#大小单元格属性都被设置为1。此设置指定需要一个32位数据来表示一个地址,并且需要一个32位数据来表示区间的大小,在serial设备中寄存器起始地址为0x4600,大小为0x100:

soc {
    #address-cells = <1>;
    #size-cells = <1>;
    serial@4600 {
        compatible = "ns16550";
        reg = <0x4600 0x100>;
        clock-frequency = <0>;
        interrupts = <0xA 0x8>;
        interrupt-parent = <&ipic>;
    };
};

使用两个32位数据表示的示例如下,表示的起始地址和大小分别是0x3001000,0x1000;0x7010000,0x400;0x7000000,0x4:

/ {
        interrupt-parent = <0x1>;
        #address-cells = <0x2>;
        #size-cells = <0x2>;
        model = "Orange Pi Zero 2";
        compatible = "allwinner,h616", "arm,sun50iw9p1";

        clocks {
                compatible = "allwinner,clk-init";
                device_type = "clocks";
                #address-cells = <0x2>;
                #size-cells = <0x2>;
                ranges;
                reg = <0x0 0x3001000 0x0 0x1000 0x0 0x7010000 0x0 0x400 0x0 0x7000000 0x0 0x4>;
        };
}

(6)reg

reg属性描述了设备在其父总线定义的地址空间内的资源的地址。最常见的意思是内存映射的IO寄存器块的偏移量和长度,但在某些总线类型上可能有不同的含义。由根节点定义的地址空间中的地址为CPU真实地址。示例可以参考上面的节点。

(7)ranges

用于描述设备地址映射,通常用于指定设备地址在系统地址空间中的映射关系,示例如下:

uart0: serial@11000 {
    compatible = "xxxxxx";
    reg = <0x13000 0x100>;                // 物理地址
    ranges = <0x0 0x13000 0x0 0x100>;     // 映射地址
};

(8)name

用于指定设备节点的名称,通常用于标识设备节点的类型或用途,示例如下:

uart0: serial@11000 {
    compatible = "xxxxxx";
    reg = <0x13000 0x100>;
    name = "serialport";
};

(9)device_type

用于指定设备节点的类型,通常用于区分设备节点的功能或类别,示例如下:

uart0: serial@11000 {
    compatible = "xxxxxx";
    reg = <0x13000 0x100>;
    device_type = "serial";
};
3.2 常见节点

(1)aliases node

aliases  节点用于定义设备的别名,可以将设备的逻辑名称映射到实际的设备节点。这样可以在设备树中使用逻辑名称来引用设备,而不必关心实际的物理地址。

aliases {
    serial0 = "/simple-bus@fe000000/serial@llc500";
    ethernet0 = "/simple-bus@fe000000/ethernet@31c000";
};

(2)memory node

节点用于描述系统的内存布局,包括内存的起始地址和大小。

memory@0 {
    device_type = "memory";
    reg = <0x000000000 0x00000000 0x00000000 0x80000000>;
};
memory@100000000 {
    device_type = "memory";
    reg = <0x000000001 0x00000000 0x00000001 0x00000000>;
};

(3)reserved-memory node

reserved-memory节点用于描述系统中保留的内存区域,这些区域可能被用于设备 DMA 缓冲区等。

reserved-memory {
    #address-cells = <2>;
    #size-cells = <2>;
    ranges;
    
    dma_reserved: buffer@90000000 {
        reg = <0x90000000 0x00400000>; // 描述一块保留给设备 DMA 缓冲区的内存,起始地址是 0x90000000,大小为 4MB
    };
};

(4)chosen node

 chosen节点用于存放一些全局的配置信息,比如引导参数等。

	chosen {
		bootargs = "earlyprintk=sunxi-uart,0x05000000 loglevel=8 initcall_debug=1 console=ttyS0 init=/init";
		linux,initrd-start = <0x0 0x0>;
		linux,initrd-end = <0x0 0x0>;
	};

(5)cpus Node

cpus 节点用于描述系统中的 CPU,而 /cpus /cpus * 节点属性用于描述每个 CPU 的相关信息,比如 CPU 的寄存器配置、中断控制器等。

cpus {
    #address-cells = <1>;
    #size-cells = <0>;
    cpu@0 {
        compatible = "arm,cortex-a53";
        reg = <0>;
        // 其他 CPU 相关属性
    };
    cpu@1 {
        compatible = "arm,cortex-a53";
        reg = <1>;
        // 其他 CPU 相关属性
    };
};

4、dts文件使用

dts文件会被编译成dtb文件,编译过程如图所示,通过编译工具dtc实现:

dtb文件经过一系列处理转换为节点供内核使用,图示为大致的处理流程:

  • 在引导加载阶段,Bootloader 会将设备树的地址传递给内核
  • 内核在启动过程中会对加载的设备树进行解析,将设备树节点转换为内核中的数据结构,如device_node。
  • 在设备初始化阶段,内核会根据解析后的设备树信息创建对应的设备结构,如platform_device。
  • 在内核启动后,可以通过加载设备树的修正补丁来动态修改设备树的内容

5、总结

文本讲解了dts文件的一般格式,简单阐述了dtb文件的解析使用流程。

文章部分内容引用官方文档《Devicetree Specification》Release v0.4,文档可在官网获取

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1387384.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

记录一次git merge后发现有些文件不对的问题,排查过程

分支进行merge&#xff08;A merge到B&#xff09;之后&#xff0c;发现string.xml中有些字段的值没有merge过来&#xff0c;一开始还以为自己是自己merge错误&#xff0c;检查了一遍自己的merge操作没有问题。 那为啥没有merge过来呢&#xff1f;有一种可能是&#xff0c;merg…

软件测试|Python数据可视化神器——pyecharts教程(十三)

使用pyecharts绘制水球图 水球图是一种有趣而视觉吸引力的数据可视化方式&#xff0c;它可以用来展示进度或百分比等信息。这方面水球图和仪表图是类似的&#xff0c;但是水球图比仪表图更为炫酷一些。像一些资源占用率等指标都是使用水球图来展示的&#xff0c;作为绘图神器&…

LaTeX 章节的使用

目录 1、介绍 2、章节的等级 3、取消编号章节 4、章节引用 1、介绍 命令\section{}标志着一个新章的开始&#xff0c;大括号内的文字为章的标题。章的编号是自动生成的&#xff0c;你也可以使用没有编号的章。 \documentclass[]{article}\begin{document}\section{Introd…

在服务器上使用Docker运行SRS Stack,推拉直播流、多平台转播、本地录制、虚拟直播、直播转码、AI字幕、其他

SRS Stack | SRS (ossrs.net) Docker​ 推荐使用Docker运行SRS Stack&#xff1a; docker run --restart always -d -it --name srs-stack -v $HOME/data:/data \-p 2022:2022 -p 2443:2443 -p 1935:1935 -p 8000:8000/udp -p 10080:10080/udp \registry.cn-hangzhou.aliyun…

设备之AP555【之一】

1、Audio Precision官网 Audio Precision 是声学及音频测试中公认的标准。AP提供了高性能声学和音频分析仪&#xff0c;配件和应用程序&#xff0c;帮助全球工程师设计&#xff0c;验证和制造消费电子、专业和工业的声学和音频产品。 APX555B 是具有三十年经验的测试设备&…

第十二章 Java内存模型与线程(二)

文章目录 12.4 Java与线程12.4.1 线程的实现12.4.2 Java线程调度12.4.3 状态转换 12.4 Java与线程 12.4.1 线程的实现 实现线程主要有三种方式&#xff1a;使用内核线程实现&#xff08;1&#xff1a; 1 实现&#xff09;&#xff0c;使用用户线程实现&#xff08;1&#xff…

内网穿透[让你在家里也能榨干学校的服务器]Yep!

内网穿透 问题&#xff1a;什么是内网穿透&#xff0c;内网穿透的作用是什么&#xff1f; 前提&#xff01;&#xff01;&#xff01;&#xff01;你得拥有超级管理员的权限&#xff0c;比如root&#xff0c;不然后面的一切免提&#xff01; 应用场景如下&#xff1a;比如你…

MOS管驱动电流计算以及分立器件驱动电路

自记&#xff1a; 1.先根据mos数据手册查找参数&#xff0c;计算电流&#xff1b; 2.分立器件驱动电路图&#xff1b; 3.分立器件选择 仔细学&#xff0c;能看懂&#xff01; 1.计算电流&#xff1a; 2.分立器件驱动电流&#xff1a;两种&#xff0c;第一种反向&#xff0c…

HCIP-3

重发布、重分布、重分发&#xff1a; ASBR同时工作于不同的路由协议中&#xff0c;然后通过各种的方式学习的条目&#xff0c;再进行共享&#xff1b; 必须存在ASBR----自治系统边界路由器--协议边界路由器需要考虑种子度量 规则&#xff1a; 将A协议发布到B协议&#xff0c…

TS快速上手

1.类型声明 let a: string //变量a只能存储字符串 let b: number //变量a只能存储数值 let c: boolean //变量a只能存储布尔值 a hello a 100 //警告&#xff1a;不能将类型“number”分配给类型“string” b 666 b 你好//警告&#xff1a;不能将类型“string”分配给类型…

重学Java 6 流程控制语句

我与我&#xff0c;至死不渝 ——24.1.15 模块重点&#xff1a; ①会使用Scanner和Random ②会使用switch以及知道case的穿透性 ③会使用if ④会使用for循环&#xff0c;while循环&#xff0c;嵌套循环 一、键盘录入_Scanner 1.概述&#xff1a;是Java定义好的一个类 2.作用&am…

把握现货黄金的基本操作技巧

在投资市场这个大舞台上&#xff0c;有各种各样的投资产品供投资者选择&#xff0c;其中黄金作为一种重要的投资资产&#xff0c;一直受到广大投资者的青睐。然而&#xff0c;黄金交易并非易事&#xff0c;需要掌握一定的操作技巧。那么&#xff0c;如何才能把握住现货黄金的操…

基础面试题整理4

1.mybatis的#{}和${}区别 #{}是预编译处理&#xff0c;${}是字符串替换#{}可以防止SQL注入&#xff0c;提高安全性 2.mybatis隔离级别 读未提交 READ UNCOMMITED&#xff1a;读到了其他事务中未提交的数据&#xff0c;造成"脏读","不可重复读","幻读&…

DBA技术栈(三):MySQL 性能影响因素

文章目录 前言一、影响MySQL性能的因素1.1 商业上的需求1.2 应用架构规划1.3 查询语句使用方式1.4 Schema的设计1.5 硬件环境 总结 前言 大部分人都一致认为一个数据库应用系统&#xff08;这里的数据库应用系统概指所有使用数据库的系统&#xff09;的性能瓶颈最容易出现在数…

ssm+vue的物流配送人员车辆调度管理系统的设计与实现(有报告)。Javaee项目,ssm vue前后端分离项项目。

演示视频&#xff1a; ssmvue的物流配送人员车辆调度管理系统的设计与实现&#xff08;有报告&#xff09;。Javaee项目&#xff0c;ssm vue前后端分离项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&…

day-10 删除排序链表中的重复元素

思路 先统计每个值出现的次数&#xff0c;然后将出现次数为一的节点链接为一个链表即可 解题方法 while(t!null){ //统计每个值出现次数 arr[t.val100]1; tt.next; } while(t!null&&arr[t.val100]!1) tt.next;//确定返回的头结点 ttt; while(t!null&&t.next…

虾皮广告数据:​如何利用广告数据优化虾皮(Shopee)销售业绩

在虾皮&#xff08;Shopee&#xff09;平台上&#xff0c;广告数据对于卖家来说是至关重要的&#xff0c;它可以帮助卖家了解广告的效果并进行相应的优化。通过监控和分析这些广告数据&#xff0c;卖家可以更好地理解广告的表现&#xff0c;调整广告策略&#xff0c;提高广告的…

QT DAY4作业

1. 头代码 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTimerEvent> #include <QTime> #include <QTextToSpeech>namespace Ui { class Widget; }class Widget : public QWidget {Q_OBJECTpublic:explicit Widget(QWidget *par…

案例129:基于微信小程序的外卖商城平台设计与实现

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…

Untiy HTC Vive VRTK 开发记录

目录 一.概述 二.功能实现 1.模型抓取 1&#xff09;基础抓取脚本 2&#xff09;抓取物体在手柄上的角度 2.模型放置区域高亮并吸附 1&#xff09;VRTK_SnapDropZone 2&#xff09;VRTK_PolicyList 3&#xff09;VRTK_SnapDropZone_UnityEvents 3.交互滑动条 4.交互旋…