中国制造网谷歌seo/搜索引擎优化有哪些要点

中国制造网谷歌seo,搜索引擎优化有哪些要点,优秀html5网站,数据分析师要考什么证DTS基本知识 dts 硬件的相应信息都会写在.dts为后缀的文件中,每一款硬件可以单独写一份xxxx.dts,一般在Linux源码中存在大量的dts文件,对于arm架构可以在arch/arm/boot/dts找到相应的dts,一个dts文件对应一个ARM的machie。 dtsi 值…

DTS基本知识

dts

硬件的相应信息都会写在.dts为后缀的文件中,每一款硬件可以单独写一份xxxx.dts,一般在Linux源码中存在大量的dts文件,对于arm架构可以在arch/arm/boot/dts找到相应的dts,一个dts文件对应一个ARM的machie。

dtsi

值得一提的是,对于一些相同的dts配置可以抽象到dtsi文件中,然后类似于C语言的方式可以include到dts文件中,对于同一个节点的设置情况,dts中的配置会覆盖dtsi中的配置。

dtc

dtc是编译dts的工具,可以在Ubuntu系统上通过指令apt-get install device-tree-compiler安装dtc工具,不过在内核源码scripts/dtc路径下已经包含了dtc工具;

scripts/dtc/Makefile 文件内容如下:

示例代码 43.2.1 scripts/dtc/Makefile 文件代码段
1 hostprogs-y := dtc
2 always := $(hostprogs-y)
3
4 dtc-objs:= dtc.o flattree.o fstree.o data.o livetree.o treesource.o \
5 srcpos.o checks.o util.o
6 dtc-objs += dtc-lexer.lex.o dtc-parser.tab.o
......

可以看出,DTC 工具依赖于 dtc.c、flattree.c、fstree.c 等文件,最终编译并链接出 DTC 这个主机文件。如果要编译 DTS 文件的话只需要进入到 Linux 源码根目录下,然后执行如下命令:

make all

或者:

make dtbs

“make all”命令是编译 Linux 源码中的所有东西,包括 zImage,.ko 驱动模块以及设备树,如果只是编译设备树的话建议使用“make dtbs”命令。

dtb

dtb(Device Tree Blob),dts经过dtc编译之后会得到dtb文件,dtb通过Bootloader引导程序加载到内核。所以Bootloader需要支持设备树才行;Kernel也需要加入设备树的支持;

基于 ARM 架构的 SOC 有很多种,一种 SOC 又可以制作出很多款板子,每个板子都有一个对应的 DTS 文件,那么如何确定编译哪一个 DTS 文件呢?我们就以 I.MX6ULL 这款芯片对应的板子为例来看一下,打开 arch/arm/boot/dts/Makefile,有如下内容:

示例代码 43.2.2 arch/arm/boot/dts/Makefile 文件代码段
381 dtb-$(CONFIG_SOC_IMX6UL) += \
382 imx6ul-14x14-ddr3-arm2.dtb \
383 imx6ul-14x14-ddr3-arm2-emmc.dtb \
......
400 dtb-$(CONFIG_SOC_IMX6ULL) += \
401 imx6ull-14x14-ddr3-arm2.dtb \
402 imx6ull-14x14-ddr3-arm2-adc.dtb \
403 imx6ull-14x14-ddr3-arm2-cs42888.dtb \
404 imx6ull-14x14-ddr3-arm2-ecspi.dtb \
405 imx6ull-14x14-ddr3-arm2-emmc.dtb \
406 imx6ull-14x14-ddr3-arm2-epdc.dtb \
407 imx6ull-14x14-ddr3-arm2-flexcan2.dtb \
408 imx6ull-14x14-ddr3-arm2-gpmi-weim.dtb \
409 imx6ull-14x14-ddr3-arm2-lcdif.dtb \
410 imx6ull-14x14-ddr3-arm2-ldo.dtb \
411 imx6ull-14x14-ddr3-arm2-qspi.dtb \
412 imx6ull-14x14-ddr3-arm2-qspi-all.dtb \
413 imx6ull-14x14-ddr3-arm2-tsc.dtb \
414 imx6ull-14x14-ddr3-arm2-uart2.dtb \
415 imx6ull-14x14-ddr3-arm2-usb.dtb \
416 imx6ull-14x14-ddr3-arm2-wm8958.dtb \
417 imx6ull-14x14-evk.dtb \
418 imx6ull-14x14-evk-btwifi.dtb \
419 imx6ull-14x14-evk-emmc.dtb \
420 imx6ull-14x14-evk-gpmi-weim.dtb \
421 imx6ull-14x14-evk-usb-certi.dtb \
422 imx6ull-alientek-emmc.dtb \
423 imx6ull-alientek-nand.dtb \
424 imx6ull-9x9-evk.dtb \
425 imx6ull-9x9-evk-btwifi.dtb \
426 imx6ull-9x9-evk-ldo.dtb
427 dtb-$(CONFIG_SOC_IMX6SLL) += \
428 imx6sll-lpddr2-arm2.dtb \
429 imx6sll-lpddr3-arm2.dtb \
......

可以看出,当选中 I.MX6ULL 这个 SOC 以后(CONFIG_SOC_IMX6ULL=y),所有使用到I.MX6ULL 这个 SOC 的板子对应的.dts 文件都会被编译为.dtb。如果我们使用 I.MX6ULL 新做了一个板子,只需要新建一个此板子对应的.dts 文件,然后将对应的.dtb 文件名添加到 dtb-$(CONFIG_SOC_IMX6ULL)下,这样在编译设备树的时候就会将对应的.dts 编译为二进制的.dtb文件。示例代码 43.2.2 中第 422 和 423 行就是我们在给正点原子的 I.MX6U-ALPHA 开发板移植Linux 系统的时候添加的设备树。

DTS 语法 

虽然我们基本上不会从头到尾重写一个.dts 文件,大多时候是直接在 SOC 厂商提供的.dts文件上进行修改。但是 DTS 文件语法我们还是需要详细的学习一遍,因为我们肯定需要修改.dts文件。大家不要看到要学习新的语法就觉得会很复杂,DTS 语法非常的人性化,是一种 ASCII文本文件,不管是阅读还是修改都很方便。本节我们就以 imx6ull-alientek-emmc.dts 这个文件为例来讲解一下 DTS 语法。

dtb文件是由booloader解析还是kernel解析?

DTB文件主要是由内核解析的,但Bootloader也在一定程度上参与处理DTB文件。以下是对这一过程的详细解释:

Bootloader对DTB文件的处理

加载DTB到内存:Bootloader的主要职责之一是在系统启动初期将操作系统内核和相关资源加载到内存中。在这个过程中,如果存在DTB文件(通常是由设备树源文件编译而来的二进制文件),Bootloader会将其加载到内存中的特定位置。例如,在U-Boot这样的Bootloader中,会将DTB文件存储在内存的某个预定义区域,以便后续内核能够找到并使用它。

告知内核DTB位置:Bootloader在将控制权交给内核之前,需要将DTB文件在内存中的地址或其他相关信息传递给内核。这样,内核在启动时就能够知道从哪里找到DTB文件,并开始对其进行解析。

内核对DTB文件的解析

验证DTB文件格式:内核首先会对加载的DTB文件进行格式验证,检查其头部信息是否正确,包括魔数、版本号等字段,以确保这是一个有效的设备树描述文件。

解析节点和属性:如果DTB文件格式正确,内核会进一步解析其中的节点和属性信息。节点代表了硬件设备或组件,而属性则描述了这些节点的各种特性和参数,如设备的型号、寄存器地址、中断号等。内核会将这些信息组织成内部的数据结构,以便后续的设备驱动程序能够方便地访问和使用。

创建设备模型:基于解析得到的设备树信息,内核会在内存中构建出整个系统的设备模型。这个设备模型反映了系统中所有硬件设备的层次结构和连接关系,为内核的设备管理和驱动程序的加载提供了基础。

综上所述,虽然Bootloader参与了DTB文件的加载和传递工作,但真正对DTB文件进行深入解析和利用的是Linux内核。通过解析DTB文件,内核能够获取硬件设备的信息,从而正确地初始化和管理这些设备,确保系统能够正常运行。

设备树dtb被解析后是存在内存里还是文件系统里?

设备树DTB文件在解析后主要存在于内存中,但也可能与文件系统存在一定关联。以下是对这一问题的详细解释:

内存中的存在形式

作为内核数据结构:设备树DTB文件在被内核解析后,其内容会被转化为一系列的内核数据结构,如device_nodeproperty等。这些数据结构存储在内存中,用于描述系统中的设备及其属性和配置信息。

内存中的保留区域:在某些情况下,设备树DTB文件可能会被加载到内存中的特定区域,以便内核能够直接访问和解析。例如,在ARM架构的系统中,设备树DTB文件通常会被加载到内存的起始地址处。

文件系统中的存在形式

/sys文件系统:内核会在/sys文件系统的/sys/firmware/fdt/目录下创建设备树的相关信息,包括设备树的字符串表(strings)和结构体(structure)部分。这些信息以文件的形式存在,用户可以通过读取这些文件来查看设备树的内容。

/proc文件系统:虽然/proc文件系统主要用于提供内核运行时的信息,但在某些情况下,它也可以用来查看与设备树相关的信息。例如,通过访问/proc/device-tree目录,可以获取到设备树的原始内容或经过处理后的信息。

综上所述,设备树DTB文件在解析后主要存在于内存中,但也可能与文件系统(如/sys和/proc)存在一定的关联,以便用户和开发者能够查看和管理设备树的内容。这种设计既保证了设备树信息的高效使用,又提供了方便的接口供外部访问和调试。

.dtsi 头文件

和 C 语言一样,设备树也支持头文件,设备树的头文件扩展名为.dtsi。在 imx6ull-alientek

emmc.dts 中有如下所示内容:

示例代码 43.3.1.1 imx6ull-alientek-emmc.dts 文件代码段
12 #include <dt-bindings/input/input.h>
13 #include "imx6ull.dtsi"

第 12 行,使用“#include”来引用“input.h”这个.h 头文件。

第 13 行,使用“#include”来引用“imx6ull.dtsi”这个.dtsi 头文件。

看到这里,大家可能会疑惑,不是说设备树的扩展名是.dtsi 吗?为什么也可以直接引用 C语言中的.h 头文件呢?这里并没有错,.dts 文件引用 C 语言中的.h 文件,甚至也可以引用.dts 文件,打开 imx6ull-14x14-evk-gpmi-weim.dts 这个文件,此文件中有如下内容:

示例代码 43.3.1.2 imx6ull-14x14-evk-gpmi-weim.dts 文件代码段#include "imx6ull-14x14-evk.dts"

可以看出,示例代码 43.3.1.2 中直接引用了.dts 文件,因此在.dts 设备树文件中,可以通过“#include”来引用.h、.dtsi 和.dts 文件。只是,我们在编写设备树头文件的时候最好选择.dtsi 后缀。

一般.dtsi 文件用于描述 SOC 的内部外设信息,比如 CPU 架构、主频、外设寄存器地址范围,比如 UART、IIC 等等。比如 imx6ull.dtsi 就是描述 I.MX6ULL 这颗 SOC 内部外设情况信息的,内容如下:

示例代码 43.3.1.3 中第 54~89 行就是 cpu0 这个设备节点信息,这个节点信息描述了I.MX6ULL 这颗 SOC 所使用的 CPU 信息,比如架构是 cortex-A7,频率支持 996MHz、792MHz、528MHz、396MHz 和 198MHz 等等。在 imx6ull.dtsi 文件中不仅仅描述了 cpu0 这一个节点信息,I.MX6ULL 这颗 SOC 所有的外设都描述的清清楚楚,比如 ecspi1~4、uart1~8、usbphy1~2、i2c1~4等等,关于这些设备节点信息的具体内容我们稍后在详细的讲解。

设备节点

设备树是采用树形结构来描述板子上的设备信息的文件,每个设备都是一个节点,叫做设备节点,每个节点都通过一些属性信息来描述节点信息,属性就是键—值对。以下是从imx6ull.dtsi 文件中缩减出来的设备树文件内容:

第 1 行,“/”是根节点,每个设备树文件只有一个根节点。细心的同学应该会发现,imx6ull.dtsi和 imx6ull-alientek-emmc.dts 这两个文件都有一个“/”根节点,这样不会出错吗?不会的,因为这两个“/”根节点的内容会合并成一个根节点。

dtsi中的根结点会和包含它的dts文件中的根结点冲突吗?

在Linux内核中,设备树(Device Tree)是一种用于描述硬件拓扑结构的数据结构。设备树通常由多个文件组成,包括.dts(Device Tree Source)文件和.dtsi(Device Tree Source Include)文件。这些文件最终会被编译成一个设备树二进制文件(Device Tree Blob,简称DTB),供内核在启动时使用。

关于DTSI中的根结点是否会和包含它的DTS文件中的根结点冲突,实际上并不会冲突。原因如下:

  1. 编译时的节点合并:当包含DTSI文件的DTS文件被编译成DTB时,编译器会将DTSI中的节点合并到DTS中的相应位置。这意味着,尽管在源代码层面看起来DTSI和DTS各自有一个根结点,但在最终编译生成的设备树中,这些节点会被合并成一个统一的树状结构。

  2. 单一的根节点:设备树本质上是一棵树,因此它只能有一个根节点。在编译过程中,所有的节点都会被整合到这个单一的根节点下,形成一个完整的设备树结构。

综上所述,DTSI中的根结点不会与包含它的DTS文件中的根结点冲突。在设备树的编译和链接过程中,这些节点会被适当地合并和管理,以确保最终生成的设备树具有一致且正确的结构。

dts中的根结点会和包含它的dts文件中的根结点冲突吗?

在Linux中,DTS中的根结点和包含它的DTS文件中的根结点实际上不会冲突

在一个DTS文件中,使用#include语句可以引用其他文件(通常是.dtsi文件),这些被引用的文件可以看作是对当前DTS文件的扩展或补充。当编译器处理这种包含关系时,它会将被包含的内容合并到主DTS文件中,从而形成一个完整的设备树结构。在这个过程中,并不会因为包含操作而产生多个根结点,最终生成的设备树仍然只有一个根结点。

其实,只要最终能保证层级关系不乱就行了,这还是很容易做到的。

第 2、6 和 17 行,aliases、cpus 和 intc 是三个子节点,在设备树中节点命名格式如下:

node-name@unit-address

其中“node-name”是节点名字,为 ASCII 字符串,节点名字应该能够清晰的描述出节点的功能,比如“uart1”就表示这个节点是 UART1 外设。“unit-address”一般表示设备的地址或寄存器首地址,如果某个节点没有地址或者寄存器的话“unit-address”可以不要,比如“cpu@0”、“interrupt-controller@00a01000”。

但是我们在示例代码 43.3.2.1 中我们看到的节点命名却如下所示:

cpu0:cpu@0

上述命令并不是“node-name@unit-address”这样的格式,而是用“:”隔开成了两部分,“:”前面的是节点标签(label),“:”后面的才是节点名字,格式如下所示:

label: node-name@unit-address

引入 label 的目的就是为了方便访问节点,可以直接通过&label 来访问这个节点,比如通过&cpu0 就可以访问“cpu@0”这个节点,而不需要输入完整的节点名字。再比如节点 “intc:interrupt-controller@00a01000”,节点 label 是 intc,而节点名字就很长了,为“interrupt-controller@00a01000”。很明显通过&intc 来访问“interrupt-controller@00a01000”这个节点要方便很多!

第 10 行,cpu0 也是一个节点,只是 cpu0 是 cpus 的子节点。

每个节点都有不同属性,不同的属性又有不同的内容,属性都是键值对,值可以为空或任意的字节流。设备树源码中常用的几种数据形式如下所示:

①、字符串

compatible = "arm,cortex-a7";

上述代码设置 compatible 属性的值为字符串“arm,cortex-a7”。

②、32 位无符号整数

reg = <0>;

上述代码设置 reg 属性的值为 0,reg 的值也可以设置为一组值,比如:

reg = <0 0x123456 100>;

③、字符串列表

属性值也可以为字符串列表,字符串和字符串之间采用“,”隔开,如下所示:

compatible = "fsl,imx6ull-gpmi-nand", "fsl, imx6ul-gpmi-nand";

上述代码设置属性 compatible 的值为“fsl,imx6ull-gpmi-nand”和“fsl, imx6ul-gpmi-nand”。

标准属性

节点是由一堆的属性组成,节点都是具体的设备,不同的设备需要的属性不同,用户可以自定义属性。除了用户自定义属性,有很多属性是标准属性,Linux 下的很多外设驱动都会使用这些标准属性,本节我们就来学习一下几个常用的标准属性。

compatible 属性

compatible 属性也叫做“兼容性”属性,这是非常重要的一个属性!compatible 属性的值是一个字符串列表,compatible 属性用于将设备和驱动绑定起来。字符串列表用于选择设备所要使用的驱动程序,compatible 属性的值格式如下所示:

"manufacturer,model"

其中manufacturer 表示厂商,model一般是模块对应的驱动名字。比如imx6ull-alientek-emmc.dts 中sound 节点是 I.MX6U-ALPHA 开发板的音频设备节点,I.MX6U-ALPHA 开发板上的音频芯片采用的欧胜(WOLFSON)出品的 WM8960,sound 节点的 compatible 属性值如下:

compatible = "fsl,imx6ul-evk-wm8960","fsl,imx-audio-wm8960";

属性值有两个,分别为“fsl,imx6ul-evk-wm8960”和“fsl,imx-audio-wm8960”,其中“fsl”表示厂商是飞思卡尔,“imx6ul-evk-wm8960”和“imx-audio-wm8960”表示驱动模块名字。sound这个设备首先使用第一个兼容值在 Linux 内核里面查找,看看能不能找到与之匹配的驱动文件,如果没有找到的话就使用第二个兼容值查。

一般驱动程序文件都会有一个 OF 匹配表,此 OF 匹配表保存着一些 compatible 值,如果设备节点的compatible 属性值和 OF 匹配表中的任何一个值相等,那么就表示设备可以使用这个驱动。比如在文件 imx-wm8960.c 中有如下内容:

示例代码 43.3.3.1 imx-wm8960.c 文件代码段
632 static const struct of_device_id imx_wm8960_dt_ids[] = {
633     { .compatible = "fsl,imx-audio-wm8960", },
634     { /* sentinel */ }
635 };
636 MODULE_DEVICE_TABLE(of, imx_wm8960_dt_ids);
637
638 static struct platform_driver imx_wm8960_driver = {
639     .driver = {
640         .name = "imx-wm8960",
641         .pm = &snd_soc_pm_ops,
642         .of_match_table = imx_wm8960_dt_ids,
643     },
644     .probe = imx_wm8960_probe,
645     .remove = imx_wm8960_remove,
646 };

第 632~635 行的数组 imx_wm8960_dt_ids 就是 imx-wm8960.c 这个驱动文件的匹配表,此匹配表只有一个匹配值“fsl,imx-audio-wm8960”。如果在设备树中有哪个节点的 compatible 属性值与此相等,那么这个节点就会使用此驱动文件。

第 642 行,wm8960 采用了 platform_driver 驱动模式,关于 platform_driver 驱动后面会讲解。此行设置.of_match_table 为 imx_wm8960_dt_ids,也就是设置这个 platform_driver 所使用的OF 匹配表。

model 属性

model 属性值也是一个字符串,一般 model 属性描述设备模块信息,比如名字什么的,比如:

model = "wm8960-audio";

model属性

设备树中的model属性是一个字符串类型的属性,用于描述设备的型号或者模块信息。以下是关于model属性的详细解释:

属性概述:

model 属性在设备树中扮演着重要的角色,它提供了设备的型号或模块名称等信息,帮助内核或其他软件组件识别和适配不同的硬件平台。

具体作用:

设备匹配:与compatible属性一起,model属性用于将设备与驱动程序进行匹配。内核在启动时会检查设备树中的model属性值,以确定加载哪个驱动程序来控制该设备。

硬件识别:通过指定设备的型号,操作系统能够更好地了解所连接的硬件,并为其分配适当的资源和配置参数。

应用场景:

在嵌入式系统中,如使用ARM架构的开发板,model属性通常用于指定开发板的型号,以便系统能够正确初始化并运行相应的软件。

在PCIe设备枚举过程中,主机可以使用设备树中的model属性来确定设备的兼容性和驱动需求。

综上所述,model属性是设备树中不可或缺的一部分,对于确保硬件的正确识别、配置以及与软件的兼容至关重要。

status 属性

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

#address-cells 和#size-cells 属性

这两个属性的值都是无符号 32 位整形,#address-cells 和#size-cells 这两个属性可以并且只能用在任何拥有子节点的节点中,用于描述子节点的地址信息。#address-cells 属性值决定了子节点 reg 属性中地址信息所占用的字长(32 位),#size-cells 属性值决定了子节点 reg 属性中长度信息所占的字长(32 位)。#address-cells 和#size-cells 表明了子节点应该如何编写 reg 属性值,一般 reg 属性都是和地址有关的内容,和地址相关的信息有两种:起始地址和地址长度,reg 属性的格式为:

reg = <address1 length1 address2 length2 address3 length3……>

每个“address length”组合表示一个地址范围,其中 address 是起始地址,length 是地址长度,#address-cells 表明 address 这个数据所占用的字长,#size-cells 表明 length 这个数据所占用的字长,比如:

第 3,4 行,节点 spi4 的#address-cells = <1>,#size-cells = <0>,说明 spi4 的子节点 reg 属性中起始地址所占用的字长为 1,地址长度所占用的字长为 0。

第 8 行,子节点 gpio_spi: gpio_spi@0 的 reg 属性值为 <0>,因为父节点设置了#address cells = <1>,#size-cells = <0>,因此 addres=0,没有 length 的值,相当于设置了起始地址,而没有设置地址长度。

第 14,15 行,设置 aips3: aips-bus@02200000 节点#address-cells = <1>,#size-cells = <1>,说明 aips3: aips-bus@02200000 节点起始地址长度所占用的字长为 1,地址长度所占用的字长也为 1。

第 19 行,子节点 dcp: dcp@02280000 的 reg 属性值为<0x02280000 0x4000>,因为父节点设置了#address-cells = <1>,#size-cells = <1>,address= 0x02280000,length= 0x4000,相当于设置了起始地址为 0x02280000,地址长度为 0x40000。

不太明白,地址和长度不都是1个字长吗?难道还有超过1个字长的地址或者长度?

参考:终于搞懂Linux 设备树中的#address-cells,#size-cells 和reg 属性-CSDN博客

再看个例子:

  alphaled {#address-cells = <1>;#size-cells = <1>;compatible = "atkalpha-led";status = "okay";reg = < 0X020C406C 0X04    /* CCM_CCGR1_BAE       */0X020E0068 0X04    /* SW_MUX_GPIO1_IO03_BASE   */0X020E02F4 0X04    /* SW_PAD_GPIO1_IO03_BASE  */0X0209C000 0X04    /* GPIO1_DR_BASE       */0X0209C004 0X04>;  /* GPIO1_GDIR_BASE       */};

这里address-cells = 1,size-cells = 1 , 表示 reg属性中,地址信息的长度是1个字长,地址长度信息也是1个字长。

可见,大部分情况下,都是1个字长。

有没有不是1个字长的?

比如:

pci@1,0 {#address-cells = <3>;#size-cells = <2>;compatible = "intel,ce4100-pci", "pci";device_type = "pci";bus-range = <1 1>;reg = <0x0800 0x0 0x0 0x0 0x0>;...
}

这里address-cells = 3,size-cells = 2 , 表示 reg属性中,地址信息的长度是3个字长,地址长度信息是2个字长,即是:address = 0x0800 0x0 0x0, length = 0x00 0x00,具体含义具体对待。此时,地址和长度均无法通过1个字长来描述。

在设备树(Device Tree)中,#size-cells 前面的 符号具有特定的含义和作用。以下是对其的解释:

属性标识作用

 区分普通属性名与特殊属性:在设备树的语法规则中,以 # 开头的属性通常具有特殊的意义或用途,与常规的属性名有所区别。这种标识方式能够让设备树的解析器快速识别和正确处理这些特殊属性,避免与普通属性产生混淆。例如,#size-cells 表示该属性是用于描述节点地址空间中尺寸信息的特殊属性,而普通的属性如 compatiblemodel 等则用于描述设备的兼容性、型号等信息。

明确属性语义类别# 符号的使用有助于将与地址、大小相关的属性归类在一起,方便管理和理解。像 #address-cells#size-cells 都属于这类描述节点地址信息的属性,通过 # 符号的统一标识,可以清晰地表明它们在语义上的关联性和特殊性。

reg 属性

reg 属性前面已经提到过了,reg 属性的值一般是(address,length)对。reg 属性一般用于描述设备地址空间资源信息,一般都是某个外设的寄存器地址范围信息,比如在 imx6ull.dtsi 中有如下内容:

上述代码是节点 uart1,uart1 节点描述了 I.MX6ULL 的 UART1 相关信息,重点是第 326 行的 reg 属性。其中 uart1 的父节点 aips1: aips-bus@02000000 设置了#address-cells = <1>、#sizecells = <1>,因此 reg 属性中 address=0x02020000,length=0x4000。查阅《I.MX6ULL 参考手册》可知,I.MX6ULL 的 UART1 寄存器首地址为 0x02020000,但是 UART1 的地址长度(范围)并没有 0x4000 这么多,这里我们重点是获取 UART1 寄存器首地址。

进一步思考。

假设reg里的数据是这样的

reg = <0x08000000 0x4000 0x08006000 0x5000 0x0800a000 0x4000>

你知道这里面哪些是地址哪些是长度吗?只知道用空格隔开了一些数据。而且,就算我们能从中看出来哪个是长度哪个是地址,但计算机怎判断呢?这就要我们告诉计算机,地址和长度所占的数据个数是怎么样的。

假设

#address-cells = <1>;

#size-cells = <1>;

那么上述6个数的顺序就是:<地址 长度 地址 长度 地址 长度>

假设

#address-cells = <1>;

#size-cells = <0>;

那么上述6个数的顺序就是:<地址 地址 地址 地址 地址 地址>,即没有哪个数据表示长度了

假设

#address-cells = <3>;

#size-cells = <3>;

那么上述6个数的顺序就是:<地址 长度>,前面三个数都表示地址,后面三个数都表示长度。

只是,一般都是

#address-cells = <1>;

#size-cells = <0>;

或者

#address-cells = <1>;

#size-cells = <1>;

ranges 属性

ranges属性值可以为空或者按照(child-bus-address,parent-bus-address,length)格式编写的数字矩阵,ranges 是一个地址映射/转换表,ranges 属性每个项目由子地址、父地址和地址空间长度这三部分组成:

child-bus-address:子总线地址空间的物理地址,由父节点的#address-cells 确定此物理地址所占用的字长。

parent-bus-address:父总线地址空间的物理地址,同样由父节点的#address-cells 确定此物理地址所占用的字长。

length:子地址空间的长度,由父节点的#size-cells 确定此地址长度所占用的字长。如果 ranges 属性值为空值,说明子地址空间和父地址空间完全相同,不需要进行地址转换,对于我们所使用的 I.MX6ULL 来说,子地址空间和父地址空间完全相同,因此会在imx6ull.dtsi中找到大量的值为空的 ranges 属性,如下所示:

第 142 行定义了 ranges 属性,但是 ranges 属性值为空。

ranges 属性不为空的示例代码如下所示:

第 5 行,节点 soc 定义的 ranges 属性,值为<0x0 0xe0000000 0x00100000>,此属性值指定了一个 1024KB(0x00100000)的地址范围,子地址空间的物理起始地址为 0x0,父地址空间的物理起始地址为 0xe0000000。

第 10 行,serial 是串口设备节点,reg 属性定义了 serial 设备寄存器的起始地址为 0x4600,

寄存器长度为 0x100。经过地址转换,serial 设备可以从 0xe0004600 开始进行读写操作,

0xe0004600=0x4600+0xe0000000。

name 属性

name 属性值为字符串,name 属性用于记录节点名字,name 属性已经被弃用,不推荐使用name 属性,一些老的设备树文件可能会使用此属性。

device_type 属性

device_type 属性值为字符串,IEEE 1275 会用到此属性,用于描述设备的 FCode,但是设备树没有 FCode,所以此属性也被抛弃了。此属性只能用于 cpu 节点或者 memory 节点。imx6ull.dtsi 的 cpu0 节点用到了此属性,内容如下所示:

在Linux的设备树(Device Tree)中,device_type属性是一个用于标识设备节点类型的字符串类型属性。以下是关于device_type属性的详细解释:

  1. 基本概念

    1. device_type属性用于描述设备树中各个设备节点的具体类型,它为内核或用户空间提供了一种识别和区分不同设备的机制。通过这个属性,系统可以知道某个节点所代表的是CPU、内存、I2C设备、SPI设备还是其他类型的设备。

  2. 常见取值

    1. CPU相关:对于CPU设备节点,device_type通常被设置为“cpu”,以明确表示该节点是一个CPU设备。

    2. 内存相关:内存设备节点的device_type一般被设置为“memory”,用于标识内存设备。

    3. 存储设备:如MMC(MultiMediaCard)设备节点,其device_type可能被设置为“mmc”,以表明这是一个MMC存储设备。

    4. 通信接口设备:例如I2C设备节点的device_type可以是“i2c”,SPI设备节点的device_type可以是“spi”,USB设备节点的device_type可以是“usb”等,这些设置有助于驱动程序正确地识别和处理相应的通信接口设备。

    5. 网络设备:以太网设备节点的device_type可能被设置为“ethernet”,从而让系统能够识别以太网相关的设备。

    6. 其他外设设备:像GPIO设备节点的device_type可以被设置为“gpio”,PWM设备节点的device_type可以是“pwm”等,以便系统对各种外设进行准确的识别和管理。

  3. 作用与意义

    1. 设备识别与驱动绑定:内核在启动或运行时会读取设备树中的信息,根据device_type属性来确定每个设备节点的类型,并将相应的设备与对应的驱动程序进行绑定。这样,当系统需要与某个设备进行交互时,就能够找到正确的驱动程序来操作该设备。

    2. 硬件资源管理:通过明确设备的类型,系统可以更好地管理和分配硬件资源。例如,对于不同类型的设备,系统可以根据其特性和需求分配适当的内存、中断等资源,以确保设备的正常运行。

    3. 兼容性与扩展性:使用device_type属性可以提高系统的兼容性和扩展性。在添加新的设备类型时,只需要在设备树中为新设备节点设置正确的device_type属性,并编写相应的驱动程序即可,无需对系统的核心代码进行大规模的修改。

综上所述,device_type属性在Linux的设备树中扮演着至关重要的角色,它不仅帮助内核和系统准确地识别和区分各种设备节点,还促进了设备与驱动程序的正确绑定以及硬件资源的有效管理。

注意,名称并不是强制的,是自定义的,只不过一般很多名称都是约定俗成的而已。

关于标准属性就讲解这么多,其他的比如中断、IIC、SPI 等使用的标准属性等到具体的例程再讲解。

特殊节点

/aliases 子节点

aliases 节点的主要功能就是定义别名,定义别名的目的就是为了方便访问节点。例如:定义 flexcan1 和 flexcan2 的别名是 can0 和 can1。

aliases {can0 = &flexcan1;can1 = &flexcan2;
};

单词 aliases 的意思是“别名”,因此 aliases 节点的主要功能就是定义别名,定义别名的目的就是为了方便访问节点。不过我们一般会在节点命名的时候会加上 label,然后通过&label来访问节点,这样也很方便,而且设备树里面大量的使用&label 的形式来访问节点。

/memory 子节点

所有设备树都需要一个memory设备节点,它描述了系统的物理内存布局。如果系统有多个内存块,可以创建多个memory节点,或者可以在单个memory节点的reg属性中指定这些地址范围和内存空间大小。

例如:一个64位的系统有两块内存空间:RAM1: 起始地址是0x0,地址空间是 0x80000000;RAM2: 起始地址是0x10000000,地址空间也是0x80000000;同时根节点下的 #address-cells = <2>和#size-cells = <2>,这个memory节点描述为:

memory@0 {device_type = "memory";reg = <0x00000000 0x00000000 0x00000000 0x80000000 0x00000000 0x10000000 0x00000000 0x80000000>;
};

或者:

memory@0 {device_type = "memory";reg = <0x00000000 0x00000000 0x00000000 0x80000000>;
};memory@10000000 {device_type = "memory";reg = <0x00000000 0x10000000 0x00000000 0x80000000>;
};

 更多待补充。

/chosen 子节点

chosen 并不是一个真实的设备, chosen 节点主要是为了 uboot 向 Linux 内核传递数据,重点是 bootargs 参数。例如:

chosen {bootargs = "root=/dev/nfs rw nfsroot=192.168.1.1 console=ttyS0,115200";
};

更多待补充。

在Linux设备树中,可以自定义属性。以下是关于自定义属性的定义和引用方法的详细解释:

自定义属性的定义

自定义属性允许用户根据特定硬件设备的特性和需求来定义属性名和属性值。这些属性在Linux内核和驱动程序中并不具有特殊的含义,而是由用户在设备树文件中定义,并在驱动程序中通过特定的API接口进行读取和处理。

自定义属性的引用

在设备树文件中定义自定义属性

  1. 自定义属性以键值对的形式存在,属性名由用户自定义,属性值可以是整数、字符串、布尔值等各种类型。例如:

&i2c1 {my-device@48 {compatible = "my-company,my-device";reg = <0x48>;example-config = <1 9600>; /* 工作模式为1,波特率为9600 */};
};

在这个例子中,example-config就是一个自定义属性,用于描述设备的特定配置选项。

在驱动程序中读取自定义属性

  1. 在Linux驱动程序中,可以使用如of_property_read_u32of_property_read_string等函数来读取设备树中的自定义属性。例如:

#include <linux>
static int my_driver_probe(struct platform_device *pdev) {struct device_node *np = pdev->dev.of_node;u32 example_config;int ret;/* 读取自定义属性example-config */ret = of_property_read_u32(np, "example-config", &example_config);if (ret) {dev_err(&pdev->dev, "Failed to read 'example-config' property");return ret;}/* 使用example_config进行设备配置 */// ...return 0;
}

在这个示例中,驱动程序在probe函数中通过of_property_read_u32函数读取了设备树中的自定义属性example-config,并根据该属性的值进行设备配置。

综上所述,Linux设备树允许用户自定义属性,并通过特定的API接口在驱动程序中读取和处理这些属性。这为用户提供了灵活的方式来描述硬件设备的特定特性和配置选项。

如何在设备树中表示和引用设备信息

先分析一个完整的设备树,是怎么表达各种外设信息的。

以imux6ull开发板为例进行说明。

这个文件里就一个设备信息

 

才这么点内容,是不是出问题了?当然不是,我们知道dts文件是可包含的,所以,最终形成的一个完整文件就是把各文件给整合起来,以根结点为起始的一个文件。 根据前面了解到的知识,这里应该是对已有外设的信息的追加,不过我们暂时不管这里,而是根据包含关系找到起始的地方,然后顺着往下看。

梳理后,有如下包含关系:

imx6ull-14x14-evk-emmc.dts包含了imx6ull-14x14-evk.dts;

imx6ull-14x14-evk.dts又包含了imx6ull.dtsi;

imx6ull.dtsi又包含了skeleton.dtsi;

skeleton:骨骼,骨架;框架;梗概,纲要

再往上就没有了,所以,先看看skeleton.dtsi文件

 

skeleton.dtsi 文件是用于设备树的通用头文件,通常被包含在其他设备树源文件(.dts 或 .dtsi)中。它定义了一些基本节点和属性,以满足设备树的基本要求。以下是对 skeleton.dtsi 文件内容的详细解释:

根节点

/ {:这是设备树的根节点,每个设备树文件有且仅有一个根节点。在包含 skeleton.dtsi 的文件中,这个根节点会与其他文件的根节点合并,最终形成一个统一的设备树结构。

地址单元和大小单元

#address-cells = <1>;:指定了该设备树中地址单元的数量。对于大多数简单的设备树节点,地址单元数量为 1 即可满足需求。这意味着在描述设备的地址信息时,使用一个单元(通常是 32 位或 64 位的值)来表示地址。例如,对于内存设备的基地址,就可以用一个这样的地址单元来指定。

#size-cells = <1>;:定义了大小单元的数量。同样,对于很多设备节点,大小单元数量设为 1 就足够了。它用于描述设备所占用的内存或资源的大小,比如内存区域的大小、寄存器块的大小等,以一个单元的值来表示具体的字节数。

chosen 节点

chosen { };:这是一个特殊的节点,通常用于在设备树中标记一些被选择或推荐的设置。在内核引导过程中,引导加载程序可能会根据这个节点中的信息来进行一些特定的配置或初始化操作。不过在 skeleton.dtsi 中,这个节点暂时没有包含任何具体的子节点或属性。

aliases 节点

aliases { };:用于创建设备树中的别名。通过别名,可以给设备树中的节点起一个更易读、更有意义的名字,方便在其他部分的设备树文件中引用。这有助于提高设备树的可读性和可维护性。但在 skeleton.dtsi 中,目前也没有具体的别名定义。

memory 节点

memory { device_type = "memory"; reg = <0 0>; };:定义了一个内存设备节点。device_type = "memory" 明确指出这是一个内存类型的设备。reg = <0 0> 表示该内存设备的起始地址为 0x00000000,大小为 0x00000000(这里的大小为 0 可能是一个占位符,实际的内存大小会在具体的设备树文件中根据硬件情况进行设置)。这个内存节点是设备树中描述系统内存的基础模板,其他具体的内存设备节点可以在继承这个节点的基础上进行修改和扩展。

总的来说,skeleton.dtsi 文件提供了设备树的基本框架和一些常用的节点定义,使得其他的设备树文件可以在此基础上进行扩展和定制,从而减少代码的重复编写,提高设备树的可维护性和可扩展性。 可见,该文件只是一个最基础的框架性模版,没有具体的设备信息。

接下来看imx6ull.dtsi这个文件,这个文件的内容比较多。

imx6ull.dtsi 文件是一个设备树包含文件(Device Tree Include File),用于描述 I.MX6ULL SoC(System on Chip)的内部外设信息。可见,是一个描述芯片信息的设备树包含文件。因此,建议不要在该文件中包含片外的外设。 不过虽然看着很长,其实总体上就那么几类信息,大部分的长度都在soc片上外设或者控制器等上面。 imx6ull.dtsi 文件是一个设备树包含文件(Device Tree Include File),用于描述 I.MX6ULL SoC(System on Chip)的内部外设信息。以下是对该文件内容的详细解释:

头文件引用

时钟、GPIO、中断控制器相关头文件:

#include <dt-bindings>:包含了与 I.MX6ULL 时钟配置相关的绑定信息,这些信息定义了时钟的各种属性、频率范围等,以便在设备树中对时钟进行准确的描述和配置。

#include <dt-bindings>:提供了 GPIO(通用输入输出端口)的相关信息,如 GPIO 的编号、功能、状态等定义,使得在设备树中可以正确地描述和使用 GPIO 引脚。

#include <dt-bindings>:包含了 ARM 通用中断控制器(GIC)的绑定信息,这对于处理 I.MX6ULL 的中断机制非常重要,通过该头文件可以在设备树中准确地设置中断控制器的属性和行为。

针脚功能相关头文件:

#include "imx6ull-pinfunc.h" 和 #include "imx6ull-pinfunc-snvs.h":这两个头文件定义了 I.MX6ULL 的针脚功能和特殊非易失性存储(SNVS)相关的针脚功能。它们指定了各个针脚的用途、电气特性等,对于连接外部设备以及正确配置芯片的引脚功能至关重要。

基础框架头文件:

#include "skeleton.dtsi":这是一个基础的设备树框架头文件,通常包含了一些通用的设备树节点定义和基本的结构信息,为后续具体的设备树描述提供了一个基础模板。

根节点及子节点

根节点:

/ {:这是设备树的根节点,所有的其他节点都是直接或间接地挂在这个根节点下面。在设备树的语法中,根节点使用反斜杠“/”表示,它是整个设备树的起点,代表了整个系统的硬件资源。

别名节点(aliases):

aliases { can0 = &amp;flexcan1; };:别名节点用于为设备树中的节点创建易于理解和使用的别名。在这里,将 &amp;flexcan1 这个节点命名为 can0,这样在其他地方引用 can0 时,实际上就是指代 flexcan1 节点。这种别名机制方便了设备树的编写和阅读,尤其是对于复杂的硬件系统,可以通过有意义的别名来快速定位和引用特定的硬件设备。

CPU 节点(cpus):

cpus { #address-cells = <1>; #size-cells = <0>; cpu0: cpu@0 { compatible = "arm,cortex-a7"; device_type = "cpu"; reg = <0>; }; };:这个节点描述了 I.MX6ULL SoC 上的 CPU 信息。其中,#address-cells = <1> 和 #size-cells = <0> 定义了地址单元和大小单元的数量,对于 CPU 节点来说,这里不需要大小单元。cpu0 是第一个 CPU 节点,其属性包括 compatible 字段,表示该 CPU 与 “arm,cortex-a7” 兼容,device_type 字段表明这是一个 CPU 类型的设备,reg 字段给出了 CPU 的寄存器地址范围,这里是 <0>,表示基地址为 0。

中断控制器节点(intc):

intc: interrupt-controller@00a01000 { compatible = "arm,cortex-a7-gic"; #interrupt-cells = <3>; interrupt-controller; reg = <0x00a01000 0x1000>, <0x00a02000 0x100>; };:该节点定义了 I.MX6ULL 的中断控制器。compatible 字段指出该中断控制器与 “arm,cortex-a7-gic” 兼容,#interrupt-cells = <3> 表示中断控制器需要 3 个单元来描述中断信息。interrupt-controller; 是一个特殊的属性,用于标识这是一个中断控制器节点。reg 字段定义了中断控制器的寄存器地址范围,这里分别是 0x00a01000 - 0x00a02000。

时钟节点(clocks):

clocks { #address-cells = <1>; #size-cells = <0>; ckil: clock@0 { compatible = "fixed-clock"; reg = <0>; #clock-cells = <0>; clock-frequency = <32768>; clock-output-names = "ckil"; }; };:此节点描述了 I.MX6ULL 的一个固定时钟。ckil 是时钟的名称,compatible 字段表示这是一个固定时钟类型,reg 字段为空,表示该时钟没有特定的寄存器地址(因为它是固定频率的时钟,不需要配置寄存器)。#clock-cells = <0> 说明不需要额外的单元来描述时钟属性,clock-frequency = <32768> 设定了时钟的频率为 32768Hz,clock-output-names = "ckil" 给出了时钟输出的名称。

系统节点(soc):

soc { #address-cells = <1>; #size-cells = <1>; compatible = "simple-bus"; interrupt-parent = <&amp;gpc>; ranges; busfreq { compatible = "fsl,imx_busfreq"; }; };:该节点代表了一个简化的总线结构,用于描述 SoC 中的总线相关信息。#address-cells = <1> 和 #size-cells = <1> 定义了地址和大小的单元数量。compatible = "simple-bus" 表示这是一个简单的总线类型。interrupt-parent = <&amp;gpc>; 指定了中断父节点是全局平台控制器(GPC),这意味着该总线的中断信号将连接到 GPC。ranges; 表示总线的范围信息(具体内容未详细展开)。busfreq 子节点进一步描述了总线频率相关的信息,这里使用了 "fsl,imx_busfreq" 作为兼容属性,但具体的频率值等信息未在这段代码中给出。

总结来说,imx6ull.dtsi 文件通过一系列的节点和属性定义,详细描述了 I.MX6ULL SoC 的内部外设信息,包括 CPU、中断控制器、时钟、总线以及特定的外围设备(如 GPMI NAND)等。这些信息对于构建基于 I.MX6ULL 的嵌入式系统的设备树至关重要,因为它们告诉操作系统如何正确地识别、配置和访问这些硬件组件。 这里先了解设备树整体的框架,后续再展开一些重点的地方来进一步说明。

再来看看imx6ull-14x14-evk.dts文件,这个文件的内容也比较长,其实就是描述特定开发板的设备信息的,也有对芯片信息的进一步补充。 imx6ull-14x14-evk.dts 文件是用于描述 i.MX6ULL 14x14 EVK(Evaluation Kit,评估套件)硬件的 Device Tree Source(设备树源)文件。以下是对该文件内容的详细解释:

头文件引用

#include <dt-bindings>:引入与输入设备相关的绑定定义,为后续描述输入设备节点提供基础信息和属性绑定。

#include "imx6ull.dtsi":包含 i.MX6ULL 芯片通用的设备树包含文件,其中定义了 i.MX6ULL 芯片相关的外设描述、时钟、中断控制器等基本信息,可在当前文件中直接使用这些预定义的节点和属性。

根节点及基本属性

/ {:根节点,代表整个设备树的根,所有其他的节点都是直接或间接挂在这个根节点下面。

model = "Freescale i.MX6 ULL 14x14 EVK Board";:定义了该设备树所对应的开发板型号,即 Freescale(现 NXP)的 i.MX6ULL 14x14 EVK 评估板。

compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ull";:指定了设备的兼容属性,表明该设备与 “fsl,imx6ull-14x14-evk” 和 “fsl,imx6ull” 兼容,这样内核在加载设备树时可以根据这些兼容字符串来匹配相应的驱动程序。

chosen { stdout-path = &amp;uart1; };:选择了默认的控制台输出设备,这里将 uart1 设置为系统启动时的默认控制台输出端口,以便在系统启动过程中输出日志信息。

内存节点

memory { reg = <0x80000000 0x20000000>; };:描述了内存区域的起始地址和大小,0x80000000 是内存的起始物理地址,0x20000000 是内存的大小,表示该评估板上有 512MB 的内存可供使用。

保留内存节点

reserved-memory {:定义了一些需要保留的内存区域,这些区域通常用于特定的硬件功能或未来的扩展,不允许常规的内存访问。

#address-cells = <1>; #size-cells = <1>; ranges;:指定了地址单元和大小单元的数量,以及使用范围来描述保留内存的区域。

linux,cma { compatible = "shared-dma-pool"; reusable; size = <0x14000000>; linux,cma-default; };:保留了一块用于 Contiguous Memory Allocator(CMA)的内存区域,大小为 0x14000000 字节(约 36MB),compatible 属性为 "shared-dma-pool",表示这是一个共享的 DMA 池,reusable 表示该内存区域可重复使用,linux,cma-default 表示这是默认的 CMA 区域。

背光节点

backlight { compatible = "pwm-backlight"; pwms = <&amp;pwm1 0 5000000>; brightness-levels = <0 4 8 16 32 64 128 255>; default-brightness-level = <6>; status = "okay"; };:描述了背光设备的相关信息。compatible 属性为 "pwm-backlight",表示该背光设备使用 PWM(脉宽调制)控制。pwms 属性指定了用于控制背光的 PWM 控制器及其参数,这里使用了 pwm1 通道 0,频率为 5MHz。brightness-levels 定义了背光的亮度级别,从 0 到 255 共 256 级亮度可调。default-brightness-level 设置了默认的亮度级别为 6。status = "okay" 表示该背光设备工作正常。

摄像头节点

pxp_v4l2 { compatible = "fsl,imx6ul-pxp-v4l2", "fsl,imx6sx-pxp-v4l2", "fsl,imx6sl-pxp-v4l2"; status = "okay"; };:定义了一个 V4L2(Video for Linux Two)接口的摄像头设备节点。compatible 属性列出了该摄像头设备所兼容的驱动类型,包括 "fsl,imx6ul-pxp-v4l2"、"fsl,imx6sx-pxp-v4l2" 和 "fsl,imx6sl-pxp-v4l2",表示该摄像头可以在使用这些 SoC(System on Chip)的开发板上通过相应的驱动程序进行视频采集等工作。status = "okay" 表示该摄像头设备工作正常。

电源管理节点

regulators { compatible = "simple-bus"; //省略... };:描述了电源管理相关的信息。compatible 属性为 "simple-bus",表示这是一个简单的电源总线。此处省略了具体的电压调节器等电源组件的定义,实际的文件中可能会详细列出各个电源域、电压调节器的类型、输出电压等信息,用于内核对电源的管理。

CPU 供电相关节点

&amp;cpu0 { arm-supply = <®_arm>; soc-supply = <®_soc>; dc-supply = <®_gpio_dvfs>; };:针对 CPU0 的供电配置节点。arm-supply、soc-supply 和 dc-supply 分别指定了 CPU 的不同供电域所使用的电源控制器或电源轨,如 ®_arm、®_soc 和 ®_gpio_dvfs,这些是在其他部分定义好的电源相关的节点,用于为 CPU 提供稳定的电源供应。

时钟节点

&amp;clks { assigned-clocks = <&amp;clks IMX6UL_CLK_PLL4_AUDIO_DIV>; assigned-clock-rates = <&amp;clks IMX6UL_CLK_PLL4_AUDIO_DIV>; };:描述了时钟相关的配置信息。assigned-clocks 和 assigned-clock-rates 属性分别指定了分配给设备的时钟源和时钟频率,这里使用了 &amp;clks IMX6UL_CLK_PLL4_AUDIO_DIV,表示使用的是 i.MX6ULL 的 PLL4 音频时钟分频后的时钟源作为设备的时钟输入,具体的时钟频率值也在其他地方定义。

其他节点

总的来说,imx6ull-14x14-evk.dts 文件通过上述各种节点和属性的定义,详细地描述了 i.MX6ULL 14x14 EVK 开发板的硬件资源和配置信息,包括内存、背光、摄像头、电源管理、CPU 供电、时钟等方面,使得操作系统内核能够正确地识别和使用这些硬件资源,从而实现对开发板的支持和管理。在实际的嵌入式系统开发中,根据具体的硬件设计和需求,还可能需要对该文件进行进一步的修改和扩展。

总体框架暂时就了解这么多,接下来,看一些重点细节。

重点其实是在imx6ull.dtsi和imx6ull-14x14-evk.dts这两个文件上,因此我们也着眼于这两个文件。

 

其中,板级相关的在这个imx6ull-14x14-evk.dts文件里,芯片级相关的在这个imx6ull.dtsi文件里,我们以板级imx6ull-14x14-evk.dts作为进一步的着手点来分析。

model、compatible、chosen、memory等属性如果作为一级属性,通常是放在板级的dts文件中,而不是放在dtsi文件中,因为这些信息基本都是用来匹配开发板的。

 

设备树中的reserved-memory节点是用于预留一段内存区域的特殊节点。以下是关于该节点的详细解释:

 

定义与用途

在设备树中,reserved-memory节点用于指定需要预留的内存区域。这些区域通常不会被操作系统或驱动程序用于常规的内存分配,而是保留给特定的硬件设备、驱动程序或系统功能使用。

典型应用场景

DMA和其他硬件加速功能:许多硬件设备(如网络接口卡、音频设备等)可能需要直接访问内存而不经过CPU,这种技术称为DMA(Direct Memory Access)。为了确保这些设备能够安全地访问内存,通常会在设备树中使用reserved-memory节点来预留所需的内存区域。

避免内存冲突:通过预留特定的内存区域,可以防止操作系统或其他驱动程序错误地将这些内存分配给其他用途,从而避免潜在的内存冲突和系统不稳定。

节点属性

reg:表示要预留的物理内存区域的起始地址和大小,格式为<address>, <size>。

compatible:可选属性,用于指定预留内存区域的兼容类型,如"shared-dma-pool"表示该内存区域可用作一组设备的DMA缓冲区共享池。

no-map:可选属性,如果存在,表示操作系统不得创建该区域的虚拟映射,也不能将其作为系统内存标准映射的一部分。

reusable:可选属性,如果存在,表示操作系统可以使用该区域中的内存,但前提是拥有该区域的设备驱动程序能够回收它。

等等。 看下这个

 

这里除了对pwm1的引用,后面还加了些其他数据,不要觉得这样不行,无非就是后面按照这种规则去解析罢了,只要能解析到数据,就没问题。 在设备树(Device Tree)中,pwms = <&pwm1 0 5000000> 是一种描述 PWM(脉宽调制)控制器和其通道配置的语法。具体来说,这行代码的含义如下:

  • pwms: 这是设备树中的一个属性,表示该设备支持 PWM 功能。

  • <&pwm1 0 5000000>: 这是属性的值,描述了具体的 PWM 控制器及其配置。

详细解释如下:

  1. &pwm1: 这是一个引用,指向一个名为 pwm1 的 PWM 控制器节点。& 符号表示这是一个对其他节点的引用。

  2. 0: 这是 PWM 通道号。在这个例子中,它表示使用 pwm1 控制器的第 0 个通道。

  3. 5000000: 这是 PWM 的频率,单位是纳秒(ns)。在这个例子中,PWM 的频率为 5,000,000 纳秒,即 5 MHz。

综合起来,这行代码的意思是:

  • 该设备使用 pwm1 控制器的第 0 个通道。

  • 该通道的 PWM 频率设置为 5 MHz。

这种配置通常用于需要精确控制信号频率的设备,如电机控制、LED 调光等应用。 这个被引用的pwm1,是在imx6ull.dtsi文件中定义的

 

并且在imx6ull-14x14-evk.dts的后面进行了追加

 

接着看电源稳压器、声卡、spi、iic等外设信息

 

 

…… 更多自行查看。 看下iomuxc节点

 

这里是个追加,其定义是在imx6ull.dtsi文件里,属于片上soc的外设子节点

 

可以对子节点直接追加,可见,如果名称是唯一的,那么是可以直接追加的。 iomuxc其实就是引脚复用控制器,这个节点里面是对引脚基本功能比如复用、驱动能力、上下拉等的描述,按照外设所用到的引脚集合在一起,比如i2c1用到的引脚

 

比如pwm1用到的所有引脚

 

等等。

pinctrl-names 属性

pinctrl-names 属性是一个字符串列表,它为引脚的不同状态或功能模式提供了名称标识。这些名称可以代表引脚的不同复用功能、电气特性配置或其他特定的工作状态等,方便在设备树中对引脚的配置进行描述和管理。通过为不同的引脚配置或功能模式指定独特的名称,如 “default”、“sleep”、“init” (自定义)等,使得设备树中的其他节点可以引用这些名称来快速定位和使用相应的引脚配置。

pinctrl-0通常用于指定设备或引脚组在默认状态下的引脚配置。这种状态通常是设备上电后或复位后的初始状态。它引用了一个在设备树的其他节点中定义的引脚组,这个引脚组包含了一组引脚及其相关的配置信息,如引脚复用功能、上下拉电阻、驱动能力等。 这两个属性貌似经常一起使用,是不是可以理解成,默认状态下所使用的引脚?

当 pinctrl-names = "default" 和 pinctrl-0 = <&pinctrl_uart1> 一起出现在设备树的一个节点中时,意味着当前节点所代表的设备或引脚组在默认状态下,将采用 pinctrl_uart1 节点所定义的引脚配置。 考虑某种应用场景,在驱动里获取pinctrl-names和pinctrl-0的属性值,然后判断pinctrl-names是否处于“default”状态,如果是的话,那就使用pinctrl-0提供的引脚信息来进行初始化。具体的行为还得看驱动是怎么去使用这些信息的。

为了进一步理解这个问题,看下这个节点,里面pinctrl-names有三个值,然后下面就分别有pinctrl-0和pinctrl-1和pinctrl-2,和pinctrl-names的三个名称是一一对应的,在驱动程序里肯定是根据不同的状态判断,去使用不同的引脚组。

iomuxc中pinctrl-names和pinctrl-0是什么属性 在设备树中,iomuxc 节点用于描述 IOMUXC(Input/Output Multiplexer Complex)的配置信息。该节点通常包含以下属性: pinctrl-names 含义:定义引脚状态,一种状态对应一个 pinctrl-x。它为引脚的不同功能或模式提供了一种命名方式,方便在设备树中对引脚配置进行分类和管理。例如,可以定义 “default”、”init”、”sleep” 等状态,来分别表示引脚在默认情况下、初始化过程中以及低功耗状态下的不同配置。 作用:通过指定不同的引脚状态,可以在不同的场景下灵活地配置引脚的功能和属性,满足系统在不同运行阶段的需求。比如在设备启动时,将引脚配置为初始化状态;在设备进入低功耗模式时,将引脚配置为睡眠状态,以降低功耗。 pinctrl-0 含义:定义第 0 种状态需要使用到的引脚组,可引用其他节点标识。它是一个引用属性,通过引用其他定义了具体引脚配置的节点,来确定在该状态下所使用的引脚设置。 作用:将引脚的实际配置信息与具体的引脚状态相关联。当设备的引脚状态为 “default” 时,pinctrl-0 所引用的节点中的引脚配置信息就会被应用到相应的引脚上,从而实现对该状态下引脚功能的设置。这样可以方便地对不同状态下的引脚配置进行集中管理和修改,提高代码的可维护性和可读性。 总的来说,pinctrl-names 和 pinctrl-0 属性在设备树的 iomuxc 节点中扮演着关键角色,它们共同协作以实现对引脚配置的灵活管理与精确控制。

iomuxc的最后一级子节点里面只有一个fls,pins属性,这个名字也是厂家自定义的,只要能跟驱动里引用节点时的名称对应起来即可。 fsl,pins 属性是一个特定于 Freescale(现为 NXP)SoC 的属性,用于描述引脚的配置信息。它通常包含一个或多个引脚配置项,每个配置项由引脚功能标识符和配置值组成。通过设置 fsl,pins 属性,可以指定引脚的复用功能以及相关的电气特性,如上下拉电阻、驱动能力等。这对于正确配置 SoC 的引脚以适应不同的外设功能至关重要。

继续

 

iomuxc_snvs是设备树中的一个属性,主要用于配置与安全非易失性存储(SNVS)子系统相关的引脚复用功能。以下是对该属性的详细解释:

基本概念

iomuxc_snvs属性通常出现在设备树节点中,用于描述某个或某些引脚与SNVS子系统之间的关联和配置信息。这些引脚可能具有特定的复用功能,通过该属性进行设置和说明。

作用范围

主要针对与SNVS子系统相关的引脚,这些引脚在系统中通常用于电源管理、安全存储或其他与安全相关的功能。

典型用途

电源管理配置:可以指定某些引脚作为电源管理引脚,如开关机控制引脚等。通过iomuxc_snvs属性的配置,可以确定这些引脚在系统中的具体功能和行为。

安全功能设置:对于涉及安全功能的引脚,如加密算法的硬件加速引脚、安全认证引脚等,使用iomuxc_snvs属性进行配置,以确保系统的安全运行。

特点

引脚复用选项有限:与一般的IOMUXC寄存器相比,iomuxc_snvs属性所涉及的引脚复用选项相对较少,通常只与特定的电源管理和安全功能相关。

安全性要求高:由于涉及到安全相关的功能,对iomuxc_snvs属性的配置和使用需要特别小心,以确保系统的安全性和稳定性。

综上所述,iomuxc_snvs属性在设备树中扮演着重要的角色,它用于配置与SNVS子系统相关的引脚复用功能,确保这些引脚能够正确地实现电源管理和安全存储等功能。

注意,设备树中的节点名称都是可以自己定义的,只要在同一层级下保持唯一即可。

设备树中写在前面的节点可以引用后面的节点吗?

在设备树中,前面的节点可以引用后面的节点。 设备树中的节点引用通常使用phandle(物理句柄)和label(标签)两种方式来表示。phandle是一个32位的整数值,用于唯一标识一个节点;label是一个字符串,用于标识一个节点。通过这些方式,一个节点可以引用另一个节点,无论它们在设备树中的位置如何。例如,可以在前面的节点中使用“&”符号和后面节点的phandle值或label来引用该节点。 设备树中引用节点是引用节点的某个属性还是引用整个节点,如何理解? 在设备树中,引用节点既可以是引用节点的某个具体属性,也可以理解为引用整个节点及其所有属性。以下是对这两种情况的具体解释:

引用节点的某个属性:

在某些情况下,一个节点可能会引用另一个节点的特定属性值。例如,一个设备节点可能需要配置其电源管理参数,而它本身没有直接定义这些参数,而是引用了另一个专门用于电源管理的节点中的相关属性。

这种引用方式使得设备树能够更加灵活地组织和管理硬件信息,避免重复定义相同的属性,同时也方便了设备的初始化和配置过程。

引用整个节点及其所有属性:

更常见的情况是,一个节点引用另一个节点时,实际上是将整个被引用节点的所有属性都纳入考虑范围。

例如,在一个复杂的嵌入式系统中,可能存在多个不同功能模块的节点,其中一个模块节点需要使用另一个模块节点的资源或配置信息。通过引用整个节点,可以方便地获取和使用该节点的所有属性,而不仅仅是其中的某个特定属性。

综上所述,设备树中的节点引用既可以指代对单个属性的引用,也可以指代对整个节点及其所有属性的引用。这种灵活性使得设备树成为一种强大的工具,能够有效地描述和管理复杂的硬件系统结构。 设备树中如果某个属性的属性值是一个节点,那么如果进一步获取属性节点的属性值? 在设备树中,如果某个属性的属性值是一个节点,要进一步获取该属性节点的属性值,可以通过以下步骤实现:

一、理解设备树结构

节点与属性:设备树由节点(Node)和属性(Property)组成。节点代表硬件设备或组件,属性用于描述节点的特性或配置参数。

属性值类型:属性的值可以是多种类型,包括整数、字符串、数组、甚至是另一个节点(这种情况较少见但确实存在)。

二、定位属性节点

查找节点:首先,需要在设备树中找到包含目标属性的节点。这通常通过遍历设备树或使用特定的查找函数(如of_find_node_by_path或of_find_node_by_name)来实现。

读取属性:一旦找到目标节点,就可以读取其属性值。如果属性值是一个节点,那么这个属性值实际上就是另一个节点的引用(可能是phandle、label或其他形式的引用)。

三、解析属性节点

获取节点引用:如果属性值是一个节点,需要解析这个引用以获取实际的节点对象。这通常涉及到将引用转换为实际的节点标识符(如phandle转换为节点指针)。

读取节点属性:一旦获得了实际的节点对象,就可以像访问普通节点一样读取其属性值。这通常通过设备树库提供的接口函数(如of_get_property)来实现。

其实就很像json数据的键的值又是一个json数据。

设备树中节点属性的值可以是另一个节点。

以下是对这一行为的详细解释:

一、设备树中的属性值类型

属性值的多样性:在设备树中,节点的属性值可以是多种数据类型,包括整数、字符串、数组(包括字节数组和字符串数组)、以及布尔值等。

节点作为属性值:除了上述基本数据类型外,设备树还支持一种特殊类型的属性值,即节点本身。这意味着一个节点的属性值可以引用或指向另一个节点。

二、实现方式

使用phandle:在设备树中,当一个节点的属性值是另一个节点时,通常使用物理句柄(phandle)来表示这种引用关系。phandle是一个32位的整数值,用于唯一标识一个节点。通过指定phandle,设备树能够清晰地表达节点之间的层次和依赖关系。

语法规则:为了在设备树中表示phandle,需要使用特定的语法。例如,在设备树源码中,可以使用“&”符号后跟节点标签名或phandle来引用其他节点。同时,为了将phandle与属性相关联,可能需要使用“<”和“>”符号来包含phandle值。

三、应用场景

硬件复用:在嵌入式系统中,多个设备或组件可能会共享相同的硬件资源(如中断控制器、时钟源等)。通过在设备树中使用节点作为属性值,可以方便地实现硬件资源的共享和复用。

模块化设计:设备树中的节点引用也有助于实现模块化设计。通过将相关的节点组织在一起,并使用属性值进行引用,可以构建出更加清晰、易于维护的设备树结构。

四、注意事项

循环引用:虽然设备树允许节点属性的值是另一个节点,但需要注意避免循环引用的情况。循环引用可能导致设备树解析器进入无限循环,从而无法正确解析设备树。

语义清晰性:当使用节点作为属性值时,应确保这种引用关系具有明确的语义意义。这有助于提高设备树的可读性和可维护性。

综上所述,设备树中节点属性的值确实可以是另一个节点,并且这种特性在嵌入式系统的硬件描述和配置中发挥着重要作用。通过合理使用节点引用和phandle机制,可以构建出更加灵活、可扩展和可维护的设备树结构。

更多补充

中断结点

 #interrupt-cells是一个整数类型的属性,用于指定在设备树的中断描述中使用多少个单元来表示一个中断。例如,如果#interrupt-cells的值为2,那么在描述每个中断时,需要使用2个单元的数据来表示相关信息。注意,不是对应的reg,具体对应着什么,暂时我也不知道,后面再看。

在设备树中,interrupt-controller属性通常是一个空属性,其作用是声明当前节点是一个中断控制器。通过设置interrupt-controller属性(即使为空),可以让设备树和系统清晰地知道该节点代表的是一个中断控制器设备。这有助于在复杂的硬件架构中快速识别和定位负责中断处理的设备,方便系统对其进行正确的配置和管理。在设备树中,存在各种不同类型的设备节点,如CPU、内存、I/O设备等。interrupt-controller属性为空可以作为一种简单的标识方式,将中断控制器与其他普通设备区分开来,避免混淆,确保系统能够准确地识别和处理中断相关的设备。

 上面的#interrupt-cells应该对应的是子结点的interrupts属性的表示个数。

 interrupts 属性是一个整数数组,用于指定与该设备相关联的中断请求信号的信息。每个元素通常包含两个主要部分信息,一是中断控制器的引用(通过 phandle 或设备树节点路径表示),二是中断编号或中断名称(具体取决于设备和平台的表示方式)。

 例如,interrupts = <&intc 23 0x04>; 这个属性值中,&intc 是中断控制器的设备树节点标签,23 是中断编号,0x04 表示中断触发类型(如上升沿触发等)。

 作用与意义

硬件中断配置:它告诉操作系统或硬件抽象层(HAL)当设备需要产生中断时,应该向哪个中断控制器发送信号,以及使用哪个中断号。这样,当设备发生特定事件(如数据接收、错误发生等)需要通知处理器时,处理器能够正确地响应并执行相应的中断服务程序。

系统资源分配和管理:系统可以根据 interrupts 属性的信息,为设备分配合适的中断处理资源,确保不同设备的中断请求能够得到及时、准确的处理,避免中断冲突和混乱。

驱动程序开发:对于设备驱动开发者来说,interrupts 属性提供了关键的信息,以便编写正确的中断处理代码。驱动程序需要根据这个属性的值来注册相应的中断处理函数,使设备能够正常工作。

常见属性值的含义

中断编号:如果 interrupts 属性值中只包含一个数字,那么这个数字通常代表中断编号。例如,在一些简单的系统中,interrupts = <5>; 表示设备使用中断编号为 5 的中断线。

中断名称:在某些情况下,可能会使用中断名称来代替中断编号。例如,interrupts = <"irq_name">; 这里的 "irq_name" 是在设备树中定义的一个中断名称标识符。这种方式可以使设备树更加易读和可维护,尤其是当中断编号较多且不易理解时。

复合值:有些复杂的设备可能会有更复杂的 interrupts 属性值,包含多个单元的复合值。这些复合值可能包括中断域、触发方式、CPU 接口信息等。例如,interrupts = <gic_ppi>; 这个属性值中,GIC_PPI 表示这是一个与通用中断控制器(GIC)相关的私有外设中断(PPI),37 是中断号,1 表示中断触发类型等信息。

总之,设备树中的interrupts属性至关重要,它不仅明确了设备的中断请求信号细节,还为系统资源分配、驱动程序开发提供了关键依据,确保了硬件中断的有效管理和设备的正常运行。 

具体还要看程序里是怎么获取的。

#clock-cells

通过指定 #clock-cells 的值,可以明确子节点的时钟信息在设备树中应该如何被表示和解析。例如,如果 #clock-cells = <2>,则表示该节点下的子节点时钟信息将使用 2 个单元的数据来描述。这有助于系统准确地理解和处理不同节点的时钟配置信息,确保硬件设备的时钟设置能够被正确地识别和应用。

芯片上的外设通常都作为soc结点的子结点。

 设备树的语法规定了属性值可以是整数、字符串、数组等多种形式。当属性值为数组时,尖括号用于标识数组的开始和结束。分开写尖括号并不影响设备树编译器对属性值的解析,因为编译器会按照设备树的语法规则正确处理这种写法。例如,对于一个包含多个数值的数组属性reg = <0x1000 0x2000 0x3000>;,无论是连续写还是分开写尖括号,如reg = <0x1000>,<0x2000>,<0x3000>;,中间以逗号或者空格隔开应该都可以,设备树编译器都能识别并将其解析为一个包含三个元素的数组。也可以分行写

reg = <0x1000>,

  <0x2000>,

  <0x3000>;

  比如:

gpio-controller

在设备树(Device Tree)中,gpio-controller 属性通常用于标识某个节点代表一个 GPIO(通用输入输出)控制器。这个属性告诉系统该节点下的硬件资源是与 GPIO 控制相关的,使得操作系统能够正确地识别和使用这些 GPIO 引脚。

使用pinctrl子系统时,我们通常都会将所有的pin引脚信息都放在一起;然后具体被哪个外设使用时,需要再在对应外设节点中引用pin信息。

目前还是没太搞明白,pin,gpio和具体外设之间的设备树的关系,所有的引脚都是pin,需要先设置好pin的复用功能、驱动能力以及上下拉等基本属性;如果是复用为gpio,那么就作为gpio这种外设功能;但是,gpio也需要依附其他外设来使用的。这里要搞清楚,gpio是一种片上外设,一般都定义在soc节点中吧?然后片外的外设,就不放在soc里面?这块还得再研究研究,捋一捋。

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

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

相关文章

C++20 中的同步输出流:`std::basic_osyncstream` 深入解析与应用实践

文章目录 一、std::basic_osyncstream 的背景与动机二、std::basic_osyncstream 的基本原理三、std::basic_osyncstream 的使用方法&#xff08;一&#xff09;基本用法&#xff08;二&#xff09;多线程环境下的使用&#xff08;三&#xff09;与文件流的结合 四、std::basic_…

C/C++蓝桥杯算法真题打卡(Day8)

一、P8780 [蓝桥杯 2022 省 B] 刷题统计 - 洛谷 算法代码&#xff1a; #include<bits/stdc.h> // 包含标准库中的所有头文件&#xff0c;方便使用各种数据结构和算法 using namespace std; // 使用标准命名空间&#xff0c;避免每次调用标准库函数时都要加 std::in…

第十三次CCF-CSP认证(含C++源码)

第十三次CCF-CSP认证 跳一跳满分题解 碰撞的小球满分题解遇到的问题 棋局评估满分题解 跳一跳 题目链接 满分题解 没什么好说的 基本思路就是如何用代码翻译题目所给的一些限制&#xff0c;以及变量应该如何更新&#xff0c;没像往常一样给一个n&#xff0c;怎么读入数据&…

MySQL:数据库基础

数据库基础 1.什么是数据库&#xff1f;2.为什么要学习数据库&#xff1f;3.主流的数据库&#xff08;了解&#xff09;4.服务器&#xff0c;数据库&#xff0c;表之间的关系5.数据的逻辑存储6.MYSQL架构7.存储引擎 1.什么是数据库&#xff1f; 数据库(Database,简称DB)&#x…

【C++】二叉树和堆的链式结构(上)

本篇博客给大家带来的是用C语言来实现堆链式结构和二叉树的实现&#xff01; &#x1f41f;&#x1f41f;文章专栏&#xff1a;数据结构 &#x1f680;&#x1f680;若有问题评论区下讨论&#xff0c;我会及时回答 ❤❤欢迎大家点赞、收藏、分享&#xff01; 今日思想&#xff…

Devops之AWS:如何安装AWS CLI

AWS 命令行界面&#xff08;AWS CLI&#xff09;是一种开源工具&#xff0c;让我们能够使用命令行 Shell 中的命令与 AWS 服务进行交互。 安装步骤&#xff1a; 下载并运行AWS CLI的MSI安装程序&#xff1a; 点击如下的链接&#xff0c;即可下载MSI安装程序&#xff1a; htt…

PH2D数据集: 用人类演示数据提升人形机器人操作能力,助力跨实体学习

2025-03-18, 由加州大学圣地亚哥分校, 卡内基梅隆大学, 华盛顿大学, 麻省理工学院等机构联合收集了PH2D数据集。该数据集包含26824个任务导向的人类演示&#xff0c;采用消费者级VR设备收集&#xff0c;提供了准确的3D手部关键点姿态和语言注释。数据集覆盖了多种操作任务、不同…

Matlab 基于专家pid控制的时滞系统

1、内容简介 Matlab 185-基于专家pid控制的时滞系统 可以交流、咨询、答疑 2、内容说明 略 在处理时滞系统&#xff08;Time Delay Systems&#xff09;时&#xff0c;使用传统的PID控制可能会面临挑战&#xff0c;因为时滞会导致系统的不稳定或性能下降。专家PID控制通过结…

E902基于bash与VCS的仿真环境建立

网上看见很多E902仿真的文章&#xff0c;但用到的编译器是类似于这种Xuantie-900-gcc-elf-newlib-x86_64-V3.0.1-20241120&#xff0c;而我按照相应的步骤与对应的编译器&#xff0c;仿真总会报错。后面将编译器换成riscv64-elf-x86_64-20210512&#xff0c;反而成功了。现在开…

SpringSecurity配置(自定义认证过滤器)

文末有本篇文章的项目源码文件可供下载学习 在这个案例中,我们已经实现了自定义登录URI的操作,登录成功之后,我们再次访问后端中的API的时候要在请求头中携带token,此时的token是jwt字符串,我们需要将该jwt字符串进行解析,查看解析后的User对象是否处于登录状态.登录状态下,将…

《UNIX网络编程卷1:套接字联网API》第1章 简介

《UNIX网络编程卷1&#xff1a;套接字联网API》第1章 简介 1.1 网络编程的核心价值与挑战 网络编程是实现跨设备通信的技术基础&#xff0c;其核心目标是通过协议栈实现数据的可靠传输与高效交换。在嵌入式系统、云计算、物联网等领域&#xff0c;网络编程能力直接决定了系统的…

D-Wave专用量子计算机登顶Science 率先展示在真实场景中的量子优势(内附下载)

内容来源&#xff1a;量子前哨&#xff08;ID&#xff1a;Qforepost&#xff09; 文丨浪味仙 排版丨浪味仙 行业动向&#xff1a;4200字丨16分钟阅读 摘要&#xff1a;加拿大专用量子计算机公司 D-Wave 在 Science 期刊发表了论文&#xff0c;题为《Beyond-Classical Compu…

jmeter将返回的数据写入csv文件

举例说明&#xff0c;我需要接口返回体中的exampleid与todoid的数据信息&#xff08;使用边界提取器先将其提取&#xff09;&#xff0c;并将其写入csv文件进行保存 使用后置处理器BeanShell 脚本实例如下 import java.io.*;// 设置要写入的文件路径 String filePath "…

Linux下Redis哨兵集群模式搭建(1主2从+3哨兵)

Linux下Redis哨兵集群模式搭建&#xff08;1主2从3哨兵&#xff09; 一、Redis哨兵模式搭建 1.安装包下载 链接: https://pan.baidu.com/s/1_n2rCMi5MHX-mVkkyMo4LA 提取码: gbra 2.新建redis目录 mkdir -p /app/redis3.解压到/app/redis目录下 tar -zxvf redis-6.2.16.ta…

20250319在荣品的PRO-RK3566开发板的buildroot系统下使用集成的QT应用调试串口UART3

stty -F /dev/ttyS3 115200 -echo cat /dev/ttyS3 & echo serialdata > /dev/ttyS3 20250319在荣品的PRO-RK3566开发板的buildroot系统下使用集成的QT应用调试串口UART3 2025/3/19 14:17 缘起&#xff1a;在荣品的PRO-RK3566开发板的buildroot系统下&#xff0c;在命令…

YOLO+OpenCV强强联手:高精度跌倒检测技术实战解析

目录 关于摔倒检测 摔倒检测核心逻辑 摔倒检测:联合多种逻辑判断 原理详细解释 1. 导入必要的库 2. 定义函数和关键点连接关系 3. 筛选有效关键点并计算边界框 4. 计算人体上下半身中心点和角度 5. 绘制关键点和连接线 6. 绘制角度标注和检测跌倒 7. 返回处理后的图…

AI入门7:python三种API方式调用本地Ollama+DeepSeek

回顾 书接上篇&#xff1a;各种方式搭建了本地知识库&#xff1a; AI入门&#xff1a;AI模型管家婆ollama的安装和使用-CSDN博客 AI入门2&#xff1a;本地AI部署&#xff0c;用ollama部署deepseek&#xff08;私有化部署&#xff09;-CSDN博客 AI入门3&#xff1a;给本地d…

内网安全-横向移动Kerberos 攻击SPN 扫描WinRMWinRSRDP

1.WinRM&WinRS 条件&#xff1a; 双方开启winrm winrs服务 2008版本以上默认开启&#xff0c;win 7默认关闭 检测使用cs内置端口扫描5985开放情况 进行连接 winrs -r:http://192.168.93.30:5985 -u:administrator -p:Whoami2021 whoami 2.内网-spn shell setspn -T …

YZi Labs 谈对 Plume 的投资:利用区块链创造现实价值的典范项目

3 月 17 日&#xff0c;YZi Labs 宣布投资 RWAfi 赛道项目 Plume&#xff0c;引发市场广泛关注。本轮融资是 Plume 在 去年 5 月和 12 月 连续两轮融资后的第三轮融资&#xff0c;代表着市场资本市场对于 Plume RWAfi 叙事以及其发展潜力的高度认可。 本次融资不仅提升了市场对…

互功率谱 cpsd

互功率谱(Cross-Power Spectral Density, CPSD)是信号处理中用于描述两个信号在频域中相关性的工具。它表示两个信号在不同频率下的功率分布及其相位关系,广泛应用于模态分析、系统辨识和信号匹配等领域。 matlab 实现 MATLAB 提供了 cpsd 函数来计算互功率谱。以下是使用 …