03_Linux设备树与设备树语法

news2024/11/14 22:43:16

目录

什么是设备树

DTS、DTB和DTC

DTS语法

dtsi头文件

设备节点

标准属性

compatible属性

model属性

        status属性

#address-cells和#size-cells属性

reg属性

ranges属性

name属性

device_type属性

根节点compatible属性

使用设备树之前设备匹配方法

使用设备树以后的设备匹配方法

向节点追加或修改内容


什么是设备树

设备树(Device Tree),将这个词分开就是“设备”和“树”,描述设备树的文件叫做DTS(DeviceTree Source),这个DTS文件采用树形结构描述板级设备,也就是开发板上的设备信息,比如CPU数量、内存基地址、IIC接口上接了哪些设备、SPI接口上接了哪些设备等等,如图所示:

在图中,树的主干就是系统总线, IIC控制器、GPIO控制器、SPI控制器等都是接到系统主线上的分支。IIC 控制器有分为IIC1和IIC2两种,其中IIC1上接了FT5206和AT24C02这两个IIC设备,IIC2上只接了MPU6050这个设备。DTS文件的主要功能就是按照图所示的结构来描述板子上的设备信息,DTS文件描述设备信息是有相应的语法规则要求的

在3.x版本以前的Linux内核中ARM架构并没有采用设备树。在没有设备树的时候 Linux是如何描述ARM架构中的板级信息呢?在Linux内核源码中大量的 arch/arm/mach-xxx和arch/arm/plat-xxx 文件夹,这些文件夹里面的文件就是对应平台下的板级信息。比如在arch/arm/mach-smdk2440.c 中有如下内容(有缩减):

上述代码中的结构体变量smdk2440_fb_info就是描述SMDK2440这个开发板上的LCD信息的,结构体指针数组smdk2440_devices描述的SMDK2440这个开发板上的所有平台相关信息。这个仅仅是使用2440这个芯片的SMDK2440开发板下的LCD信息, SMDK2440开发板还有很多的其他外设硬件和平台硬件信息。使用2440这个芯片的板子有很多,每个板子都有描述相应板级信息的文件,这仅仅只是一个2440。随着智能手机的发展,每年新出的ARM架构芯片少说都在数十、数百款, Linux内核下板级信息文件将会成指数级增长!这些板级信息文件都是.c或.h文件,都会被硬编码进Linux内核中,导致Linux内核“虚胖”。就好比你喜欢吃自助餐,然后花了100多到一家宣传看着很不错的自助餐厅,结果你想吃的牛排、海鲜、烤肉基本没多少,全都是一些凉菜、炒面、西瓜、饮料等小吃,相信你此时肯定会脱口而出一句骗子。同样的,当Linux之父linus看到ARM社区向Linux内核添加了大量“无用”、冗余的板级信息文件,不禁的发出了一句"This whole ARM thing is af*cking pain in the ass"。从此以后ARM社区就引入了PowerPC等架构已经采用的设备树(Flattened Device Tree),将这些描述板级硬件信息的内容都从Linux内中分离开来,用一个专属的文件格式来描述,这个专属的文件就叫做设备树,文件扩展名为.dts。一个SOC可以作出很多不同的板子,这些不同的板子肯定是有共同的信息,将这些共同的信息提取出来作为一个通用的文件,其他的.dts文件直接引用这个通用文件即可,这个通用文件就是.dtsi文件,类似于C语言中的头文件。一般.dts描述板级信息(也就是开发板上有哪些IIC设备、SPI设备等), .dtsi 描述SOC级信息(也就是SOC 有几个CPU、主频是多少、各个外设控制器信息等)。

这个就是设备树的由来,简而言之就是, Linux内核中ARM架构下有太多的冗余的垃圾板级信息文件,导致linus震怒,然后ARM社区引入了设备树。

DTS、DTB和DTC

设备树源文件扩展名为.dts,但是我们在前面移植Linux的时候却一直在使用.dtb文件,那么 DTS和DTB这两个文件是什么关系呢?DTS是设备树源码文件,DTB是将DTS编译以后得到的二进制文件。将.c文件编译为.o 需要用到gcc 编译器,那么将.dts 编译为.dtb需要什么工具呢?需要用到DTC工具! DTC工具源码在Linux内核的scripts/dtc目录下,scripts/dtc/Makefile文件内容如下:

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

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

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

 可以看出,当选中I.MX6ULL这个SOC以后(CONFIG_SOCIMX6ULL=y),所有使用到I.MX6ULL这个SOC的板子对应的.dts文件都会被编译为.dtb。如果我们使用I.MX6ULL新做了一个板子,只需要新建一个此板子对应的.dts文件,然后将对应的.dtb文件名添加到 dtb$(CONFIG_SOCIMX6ULL)下,这样在编译设备树的时候就会将对应的.dts编译为二进制的.dtb文件。

示例代码43.2.2中第422和423行就是我们在给正点原子的i.MX6U-ALPHA开发板移植Linux系统的时候添加的设备树。关于.dtb文件怎么使用这里就不多说了。

可以看出,当选中I.MX6ULL这个SOC以后(CONFIG_SOCIMX6ULL=y),所有使用到I.MX6ULL这个SOC的板子对应的.dts文件都会被编译为.dtb。如果我们使用I.MX6ULL新做了一个板子,只需要新建一个此板子对应的.dts文件,然后将对应的.dtb文件名添加到 dtb$(CONFIG_SOCIMX6ULL)下,这样在编译设备树的时候就会将对应的.dts编译为二进制的.dtb文件。

示例代码43.2.2中第422和423行就是我们在给正点原子的I.MX6U-ALPHA开发板移植Linux系统的时候添加的设备树。关于.dtb文件怎么使用这里就不多说了

DTS语法

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

dtsi头文件

和C语言一样,设备树也支持头文件,设备树的头文件扩展名为.dtsi。在 imx6ull-alientekemmc.dts中有如下所示内容:

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

第13行,使用“#include”来引用“imx6ull.dtsi”这个.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中直接引用了.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所有的外设都描述的清清楚楚,比如ecspil~4、uart1~8、usbphy1~2、i2c1~4等等。

设备节点

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

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

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

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

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

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

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

很明显通过&intc来访问"interrupt-controller@00a01000"这个节点要方便很多!

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

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

标准属性

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

compatible属性

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

其中manufacturer表示厂商,model一般是模块对应的驱动名字。

比如imx6ull-alientek.emmc.dts中sound节点是I.MX6U-ALPHA开发板的音频设备节点, I.MX6U-ALPHA开发板上的音频芯片采用的欧胜(WOLFSON)出品的WM8960, Sound节点的compatible属性值如下:

 属性值有两个,分别为“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中有如下内容:

 第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匹配表。

第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属性描述设备模块信息,比如名字什么的,比如:

status属性

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

#address-cells和#size-cells属性

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

 每个"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>,因为父节点设置了#addresscells=<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行,子节点dep: dep@02280000的reg属性值为<0x02280000 0x4000>,因为父节点设置了#address-cells=<1>, #size-cells=<1>, address=0x02280000, length=0x4000,相当于设置了起始地址为0x02280000,地址长度为0x40000

reg属性

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

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

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节点用到了此属性,内容如下所示:

根节点compatible属性

每个节点都有compatible属性,根节点"/”也不例外, imx6ull-alientek-emmc.dts文件中根节点的compatible属性内容如下所示:

 可以看出, compatible有两个值:“fsl,imx6ull-14x14-evk”和“fsl,imx6ull”。前面我们说了,设备节点的compatible属性值是为了匹配Linux内核中的驱动程序,那么根节点中的compatible属性是为了做什么工作的?通过根节点的compatible属性可以知道我们所使用的设备,一般第一个值描述了所使用的硬件设备名字,比如这里使用的是“imx6ull-14x14-evk”这个设备,第二个值描述了设备所使用的SOC,比如这里使用的是“imx6ull”这颗SOC。Linux内核会通过根节点的compoatible属性查看是否支持此设备,如果支持的话设备就会启动Linux内核。接下来我们就来学习一下Linux内核在使用设备树前后是如何判断是否支持某款设备的。

使用设备树之前设备匹配方法

在没有使用设备树以前,uboot会向 Linux 内核传递一个叫做machine id的值,machine id也就是设备ID,告诉Linux内核自己是个什么设备,看看Linux内核是否支持。Linux内核是"支持很多设备的,针对每一个设备(板子), Linux内核都用MACHINE_START和MACHINE_END

来定义一个machine_desc结构体来描述这个设备,比如在文件 arch/arm/mach-imx/machmx35 3ds.c中有如下定义:

 上述代码就是定义了"Freescale MX35PDK”这个设备,其中MACHINE_START和MACHINE END定义在文件arch/arm/include/asm/mach/arch.h中,内容如下:

 根据MACHINE_START和MACHINE_END的宏定义,将示例代码43.3.4.2展开后如下所示:

 从示例代码43.3.4.3中可以看出,这里定义了一个machine_desc类型的结构体变量mach_desc_MX35_3DS,这个变量存储在".arch.info.init”段中。

第4行的MACH_TYPE_MX35_3DS 就是“Freescale MX35PDK ”这 个 板子的 machine id 。MACH-TYPE-MX35-3DS定义在文件include/generated/mach-types.h中,此文件定义了大量的machine id,内容如下所示:

 第287行就是MACH_TYPE_MX35_3DS的值,为1645。前面说了,uboot会给Linux内核传递 machine id这个参数,Linux内核会检查这个machine.id,其实就是将machine id与示例代码 43.3.4.3中的这些MACH_TYPE_XXX宏进行对比,看看有没有相等的,如果相等的话就表示 Linux内核支持这个设备,如果不支持的话那么这个设备就没法启动Linux内核。

使用设备树以后的设备匹配方法

当Linux内核引入设备树以后就不再使用MACHINE_START了,而是换为了

DT_MACHINE_START

DT_MACHINE_START也定义在文件arch/arm/include/asm/mach/arch.h里面,定义如下:

 可以看出, DT_MACHINE-START和MACHINE-START基本相同,只是.nr的设置不同,在DT_MACHINE_START里面直接将.nr设置为~0。说明引入设备树以后不会再根据machineid 来检查Linux内核是否支持某个设备了。

打开文件arch/arm/mach-imx/mach-imx6ul.c,有如下所示内容:

 machine_desc结构体中有个.dt_compat成员变量,此成员变量保存着本设备兼容属性,示例代码43.3.4.5中设置.dt_compat =imx6ul_dt_compat, imx6ul_dt_compat表里面有"fsl,imx6ul"和"fsl,imx6ull"这两个兼容值。只要某个设备(板子)根节点“/”的 compatible 属性值与imx6ul_dt_compat 表中的任何一个值相等,那么就表示Linux内核支持此设备。imx6ull-alientekemmc.dts中根节点的compatible 属性值如下:

 其中"fsl,imx6ull"与imx6ul_dt_compat中的"fsl,imx6ull"匹配,因此I.MX6U-ALPHA开·发板可以正常启动Linux内核。如果将imx6ull-alientek-emmc.dts根节点的compatible属性改为其他的值,比如:

 重新编译DTS,并用新的DTS启动 Linux内核,结果如图43.3.4.1所示的错误提示:

 当我们修改了根节点compatible属性内容以后,因为Linux内核找不到对应的设备,因此Linux内核无法启动。在uboot输出Starting kernel...以后就再也没有其他信息输出了。

接下来我们简单看一下Linux内核是如何根据设备树根节点的compatible属性来匹配出对应的machine_dese, Linux内核调用start_kernel函数来启动内核, start_kernel 函数会调用setup_arch函数来匹配machine_desc,setup_arch函数定义在文件 arch/arm/kernel/setup.c 中,函数内容如下(有缩减);

 第918行,调用setup_machine_fdt函数来获取匹配的machine_desc,参数就是atags的首·地址,也就是uboot传递给Linux内核的dtb文件首地址, setup_machine_fdt函数的返回值就是找到的最匹配的machine desc。

函数setup_machine_fdt定义在文件arch/arm/kernel/devtree.c中,内容如下(有缩减):

 第218行,调用函数of_flat_dt_match_machine来获取匹配的machine_desc,参数mdese_best是默认的machine_desc,参数arch_get_next_mach是个函数,此函数定义在定义在arch/arm/kernel/devtree.c文件中。找到匹配的machine_desc的过程就是用设备树根节点的compatible属性值和Linux内核中machine_desc下.dt_compat的值比较,看看那个相等,如果相等的话就表示找到匹配的machine_desc, arch_get_next_mach函数的工作就是获取Linux内核中下一个machine desc结构体。

最后再来看一下of_flat_dt_match_machine函数,此函数定义在文件drivers/of/fdt.c中,内容如下(有缩减):

第714行,通过函数 of_get_flat_dt_root 获取设备树根节点。

第715-720行,此循环就是查找匹配的machinedesc过程,

第716行的of_flat_dt_match函数会将根节点compatible属性的值和每个machine_desc 结构体中.dt_compat的值进行比较,直至找到匹配的那个machine_desc。

总结一下, Linux内核通过根节点compatible属性找到对应的设备的函数调用过程,如图所示:

向节点追加或修改内容

产品开发过程中可能面临着频繁的需求更改,比如第一版硬件上有一个IIC接口的六轴芯片 MPU6050,第二版硬件又要把这个MPU6050更换为MPU9250等。一旦硬件修改了,我们就要同步的修改设备树文件,毕竟设备树是描述板子硬件信息的文件。假设现在有个六轴芯片fxls8471, fxls8471 要接到I.MX6U-ALPHA开发板的 I2C1接口上,那么相当于需要在 i2c1 这个节点上添加一个fxls8471子节点。先看一下I2C1接口对应的节点,打开文件 imx6ull.dtsi 文件,找到如下所示内容:

 示例代码43.3.5.1就是I.MX6ULL的I2C1节点,现在要在i2cl节点下创建一个子节点,这个子节点就是fxls8471,最简单的方法就是在i2c1下直接添加一个名为fxls8471的子节点,如下所示:

 第947~950行就是添加的fxls8471这个芯片对应的子节点。但是这样会有个问题!i2c1节点是定义在imx6ull.dtsi文件中的,而imx6ull.dtsi是设备树头文件,其他所有使用到I.MX6ULL这颗SOC的板子都会引用imx6ull.dtsi这个文件。直接在i2c1节点中添加fxls8471就相当于在其他的所有板子上都添加了fxls8471这个设备,但是其他的板子并没有这个设备啊!因此,按照示例代码43.3.5.2这样写肯定是不行的。

这里就要引入另外一个内容,那就是如何向节点追加数据,我们现在要解决的就是如何向i2cl1节点追加一个名为fxls8471的子节点,而且不能影响到其他使用到I.MX6ULL的板子。I.MX6U-ALPHA开发板使用的设备树文件为imx6ull-alientek-emmc.dts,因此我们需要在imx6ull-alientek-emmc.dts文件中完成数据追加的内容,方式如下:

 第1行, &i2c1表示要访问i2c1这个label所对应的节点,也就是imx6ull.dtsi中的"i2c1:- i2c@021a0000"

第2行,花括号内就是要向i2c1这个节点添加的内容,包括修改某些属性的值。

打开imx6ull-alientek-emmc.dts,找到如下所示内容:

 示例代码43.3.5.4就是向i2cl1节点添加/修改数据,比如第225行的属性“clock-frequency”就表示i2c1时钟为100KHz "clock-frequency”就是新添加的属性。

第228行,将status属性的值由原来的disabled改为okay。

第230-234行,i2c1子节点mag3110,因为NXP官方开发板在12C1上接了一个磁力计芯片mag3110,正点原子的I.MX6U-ALPHA开发板并没有使用mag3110。

第236-242行,i2c1子节点fxls8471,同样是因为NXP官方开发板在I2C1上接了fxls8471这颗六轴芯片。

因为示例代码43.3.5.4中的内容是imx6ull-alientek-emmc.dts这个文件内的,所以不会对使用I.MX6ULL这颗SOC的其他板子造成任何影响。这个就是向节点追加或修改内容,重点就是通过&label来访问节点,然后直接在里面编写要追加或者修改的内容。

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

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

相关文章

K8S之 metrics-server 组件(十八)

首先下载&#xff1a;K8S之 metrics-server 组件 metrics-server 是一个集群范围内的资源数据集和工具&#xff0c;同样的&#xff0c;metrics-server 也只是显示数据&#xff0c;并不提供数据存储服务&#xff0c;主要关注的是资源度量 API 的实现&#xff0c;比如 CPU、…

重塑癌细胞嚣张形象!《自然》重磅论文显示,癌细胞不仅懒还很节俭

▎药明康德内容团队编辑 在我们的印象中&#xff0c;癌细胞都是身体内失去控制的猛兽&#xff0c;它们会疯狂地复制、转移&#xff0c;形成巨大的肿瘤。因此过去很长一段时间内我们都认为肿瘤是一个对资源极度贪婪的群体&#xff0c;比如一百年前&#xff0c;生理学家就发现癌…

vue2.6源码学习:数据变化监听原理之数据驱动视图(observer)

上次我们看vue2.6源码的时候&#xff0c;大概看了一下整体的项目结构目录。主要是里面的Observer和vdom这两个文件夹。 也是vue里面最核心的两个文件夹&#xff0c;今天我们继续来学习。 instance文件夹是用来做什么的 这个也是vue比较核心的一块&#xff0c;这个是与vuejs实例…

UVM中uvm_config_db机制背后的大功臣

1. 前言 本次讲一下UVM中的uvm_config_db&#xff0c;在UVM中提供了一个内部数据库&#xff0c;可以在其中存储给定名称下的值&#xff0c;之后可以由其它TB组件去检索。这样的数据库允许我们以不同的名称存储不同的配置设置&#xff0c;这些配置可以在需要时潜在地配置TB组件…

spring.session 随笔0 集成设计

0. 上个月划水时间关注的&#xff0c;最近断断续续的了解了一些 RUNOOB redis命令:APPEND 整合shiro实现分布式session同步(定制cacheManager) 我想想&#xff0c;还是照自己思绪发散的顺序开始描述这块的内容吧&#xff0c;可能侧重点有些奇怪。 由于工程使用的spring.boot.…

树莓派+Docker+cpolar(内网穿透)+Nignx

首先安装Raspberry Pi Imager&#xff0c;用于给SD卡安装系统镜像。 使用Raspberry Pi Imager&#xff08;树莓派镜像烧录器&#xff09;烧录镜像文件到SD中&#xff0c;操作步骤如下图所示&#xff1a; docker安装nginx提供web服务 获取最新版本的docker安装包&#xff1a; su…

linux上启动两个nginx实例

一台机器上启动两个nginx实例&#xff0c;主要是端口冲突问题&#xff0c;另外&#xff0c;如果一个是通过编译安装&#xff0c;另一个是拷贝的&#xff0c;那么还需要修改静态文件根路径。 这里&#xff0c;我第一个nginx是通过源码编译安装&#xff0c;安装目录是默认的/usr/…

live555交叉编译

下载live555最新源码&#xff1a;http://www.live555.com/liveMedia/public/live555-latest.tar.gz 如果是要下载具体的live555版本&#xff0c;比如2023.06.14发布的版本&#xff0c;则可以浏览器输入&#xff1a;http://www.live555.com/liveMedia/public/live.2023.06.14.t…

GPT 模型的工作原理 你知道吗?

动动发财的小手&#xff0c;点个赞吧&#xff01; Source[1] 简介 当我使用 GPT 模型编写我的前几行代码时是 2021 年&#xff0c;那一刻我意识到文本生成已经到了一个拐点。在此之前&#xff0c;我在研究生院从头开始编写语言模型&#xff0c;并且我有使用其他文本生成系统的经…

GPT-4满分通过MIT本科数学考试这套提示词火了

万万想不到啊&#xff0c;MIT数学考试&#xff0c;被GPT-4攻破了&#xff1f;&#xff01; 突然有人在最新论文工作中高调宣布&#xff1a; GPT-4在MIT的数学和EECS&#xff08;电气工程和计算机科学系&#xff09;本科学位考试中&#xff0c;表现出的能力完全满足毕业要求。…

图解左连接、右连接、内连接、全连接(小白入门)

目录 一、七种连接情况二、左连接具体例子&#xff1a;力扣数据库题目 175. 组合两个表答案1. 连接条件为&#xff1a;on Person.PersonId Address.personId2. 连接条件为&#xff1a;on Person.PersonId ! Address.personId 三、左连接不包含内连接四、右连接五、右连接不包含…

利用腾讯云函数隐藏C2服务器

1、简介 腾讯云函数&#xff0c;可以为企业和开发者提供无服务器执行环境&#xff0c;无需购买和管理服务器&#xff0c;只需要在腾讯云上使用平台支持的语言编写核心代码并设置代码运行的条件&#xff0c;即可在腾讯云基础设施上弹性 安全地运行代码。 C2服务器所有流量通过腾…

CSS入门(网络安全方向)——id与class

CSS (Cascading Style Sheets&#xff0c;层叠样式表&#xff09;&#xff0c;是一种用来为结构化文档&#xff08;如 HTML 文档或 XML 应用&#xff09;添加样式&#xff08;字体、间距和颜色等&#xff09;的计算机语言&#xff0c;CSS 文件扩展名为 .css。 通过使用 CSS 我…

Python电商数据分析系列-薪资预测

Python电商数据分析系列-薪资预测 学习目标&#xff1a; 快速掌握简单且常用的数据分析任务 自己实现预测简单预测任务 学习内容&#xff1a; 搭建 Java 开发环境掌握 Java 基本语法掌握条件语句掌握循环语句 学习对象 想快速入门的本科生转行人员想学习新技能&#xff0c…

【Python】遇到 from PIL import Image 报错怎么办?

嗨害大家好鸭&#xff01;我是小熊猫~ 很久之前有一个辛苦的小程序员 它在做验证码识别的的时候 遇上了一个小小的错误沙堆 经过它一点也不辛苦的努力&#xff0c;解决了它 于是它决定把这个宝贵的经历分享给大家~ 问题的出现&#xff1a; 前方出现红色波浪线 开始感到有一…

基于风险的测试

测试级别划分 测试级别的划分能对应解决软件开发的复杂性问题。将一个大规模复杂的系统分解&#xff0c;从小的模块开始&#xff08;单元测试&#xff09;&#xff0c;逐步放大到整个系统级别。 测试类型的设计和安排&#xff0c;将测试类型安排在最适合对应的测试级别中来识别…

精准医疗、空间组学、细胞图谱,腾讯AI Lab用深度学习助力生命科学研究

近日&#xff0c;腾讯 AI Lab 三项研究分别入选国际顶级学术期刊 Nature Methods 和 Nature Communications&#xff0c;再次展示了在生命科学前沿领域上国际领先的技术实力。 这三项研究成果都属于生物细胞研究中的空间组学技术&#xff0c;对于推动精准医疗、细胞图谱绘制、人…

lua自动回收机制gc的理解

gc主要回收哪些垃圾&#xff1f; 在 Lua 中&#xff0c;垃圾回收&#xff08;garbage collection&#xff0c;简称 GC&#xff09;机制主要用于回收动态分配的内存和关闭未关闭的文件句柄。具体来说&#xff0c;Lua 的 GC 机制主要用于回收以下类型的垃圾&#xff1a; 对象&am…

力扣日记剑指 Offer II 003

1. 题目 LeetCode 剑指 Offer II 003. 前 n 个数字二进制中 1 的个数 1.1 题意 计算 0 到 n 之间的每个数的二进制表示中 1 的个数 1.2 分析 看时间复杂度&#xff0c;O(32n)应该能过&#xff08;也就是每个数一位一位去数1的个数&#xff09;&#xff0c;知道low-bit这个运…

插入排序代码

时间复杂度O&#xff08;n&#xff09;