当前位置:   article > 正文

设备树插件dtbo介绍与应用_linux dtbo

linux dtbo

环境介绍

硬件:韦东山T113工控板
软件:Tina5.0 SDK

设备树插件简介

什么是设备插件

设备树插件DTBO(Device Tree Blob Overlay)是一种用于Linux内核和嵌入式系统的重要机制,主要用于动态地修改或扩展系统运行时的设备树配置。

为什么要用设备树插件

使用设备树插件的话,可以根据具体的外设来定制设备树插件,做到灵活替换。比如一个单板需要适配多种不同型号的屏幕,可以提前为每个屏幕做好一个设备树插件,用到哪个屏就动态替换对应的设备树插件。而不用换屏幕时,又去修改原始设备树文件,这样又得重新编译,重新烧录。

如何生成设备树插件

设备树插件语法

/dts-v1/;
/plugin/;

 / {
    fragment@0 {
        target-path = "/can@0x0";
        __overlay__ {
            /*在此添加要插入的节点*/
        };
    };

    fragment@1 {
        target-path = "/can@0x1";
        __overlay__ {
            /*在此添加要插入的节点*/
        };
    };
 };
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 头部是作为一个 overlay 的描述:
    • /dts-v1/:指定 dts 版本;
    • /plugin/:表示设备树插件中可以引用设备树中的节点。因为这些节点在设备树插件中是未定义的,要加上/plugin/才可使用;
  • 然后有个/节点,然后需要覆盖的地方用fragment@x作为节点名称:
    • target-path = "/can@0x0":为需要覆盖的节点路径;
    • __overlay__:我们要插入的设备及节点或者要引用(追加)的设备树节点放在__overlay__{}内。

设备树插件语法举例

例如现在要利用设备树插件将can0禁用。
1、查看原始设备树board.dts,确定can0的节点路径:
image.png
2、可以发现,can0节点是直接挂在根节点下的,所以插件中要覆盖的节点路径就为/+ can@0x0

/dts-v1/;
/plugin/;

 / {
    fragment@0 {
        target-path = "/can@0x0";	//需要覆盖的节点路径
        __overlay__ {
            /*在此添加要插入的节点*/
        };
    };
 };
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

3、在__overlay__中按需加入或修改设备的属性,此例要将can0禁用,所以设置status为disabled:

/dts-v1/;
/plugin/;

 / {
    fragment@0 {
        target-path = "/can@0x0";		//需要覆盖的节点路径
        __overlay__ {
            #address-cells = <1>;
    		#size-cells = <0>;
    		compatible = "allwinner,sun8i-can";
    		device_type = "can0";
    		id = <0>;
    		status = "disabled";	//禁用can0
        };
    };
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

4、若也要禁用can1,可再加一个fragment@1节点:

/dts-v1/;
/plugin/;

 / {
    fragment@0 {
        target-path = "/can@0x0";		//需要覆盖的节点路径
        __overlay__ {
            #address-cells = <1>;
    		#size-cells = <0>;
    		compatible = "allwinner,sun8i-can";
    		device_type = "can0";
    		id = <0>;
    		status = "disabled";		//禁用can0
        };
    };

    fragment@1 {
        target-path = "/can@0x1";		//需要覆盖的节点路径
        __overlay__ {
            #address-cells = <1>;
    		#size-cells = <0>;
    		compatible = "allwinner,sun8i-can";
    		device_type = "can1";
    		id = <0>;
    		status = "disabled";		//禁用can1
        };
    };
     
 };
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

编译设备树插件

dtc -I dts -O dtbo -o kernel-overlay-can.dtbo kernel-overlay-can.dts
  • 1
  • dtc:这是 Device Tree Compiler 的命令行工具
  • -I dts:指定输入文件的格式为 dts(Device Tree Source)
  • -O dtb:指定输出文件的格式为 dtb(Device Tree Blob)
  • -o kernel-overlay-can.dtb:指定输出文件的名称为 kernel-overlay-can.dtb
  • kernel-overlay-can.dts:输入文件的名称

常见的编译命令都是上面这样,但使用上面命令会报设备树语法错误,不知道是不是dtc编译器的问题。使用下面命令可以正常编译:

<sdk>/out/t113/kernel/build/scripts/dtc/dtc -I dts -O dtb -o kernel-overlay-can.dtb kernel-overlay-can.dts
  • 1
  • <sdk>/.../dtc:使用tina sdk内核里的dtc
  • -O dtb:这里的指定的输出类型是dtb而不是dtbo
  • -o kernel-overlay-can.dtb:输出文件的后缀也是dtb

至此,设备树插件编译成功。

设备树插件应用

内核配置

配置CONFIG_OF_OVERLAY = y

Device Drivers 
    -> Device Tree and Open Firmware support 
        -> [*]Device Tree overlays
  • 1
  • 2
  • 3

image.png

应用

设备树覆盖前的CAN功能是正常的:
image.png

设置工作设备树地址

【以下命令均在uboot命令行执行】

  • 可以通过uboot启动信息,查看设备树地址。下面红框内容表明,工作设备树从0x44851e58切换到了0x44831e58,实际就是从uboot设备树切换到了kernel设备树:

image.png

  • 设置工作设备树为kernel设备树,也可以不设置,因为此时已切换到了kernel设备树:
fdt addr 0x44831e58
  • 1

加载设备树插件到内存

  • 从emmc的boot-resource分区的kerneldtbo文件夹加载设备树插件到内存(据实际情况自行加载,在本文最后会简单介绍一下内存地址如何确定):
fatload mmc 2:1 0x43000000 kerneldtbo/kernel-overlay-can.dtb
fdt resize 8192
  • 1
  • 2

设备树覆盖

  • 将内存0x43000000处的设备树插件覆盖到工作设备树:
fdt apply 0x43000000
  • 1

启动

boot
  • 1

验证

此时CAN测试会提示找不到CAN端口,说明设备树插件覆盖成功:
image.png

总结

问题

1、设备树插件里所要修改的节点,一定要在工作设备树中存在,否则fat apply时会提示FDT_ERR_NOTFOUND错误:
image.png
2、关于设备树插件加载到指定地址的这个“地址”是如何确定的,下面解释一下,但不严谨:
在内核cmdline加上memblock=debugbootmem_debug=1两个参数,在内核启动时,会打印reserved memory详细信息。
重启开发板,会有如下类似的提示信息:

Starting kernel ...
...
...
memblock_reserve: [0x40100000-0x40eabcef] arm_memblock_init+0x20/0x78
memblock_reserve: [0x40004000-0x40007fff] arm_memblock_init+0x24/0x78
memblock_reserve: [0x41800000-0x4181ffff] arm_memblock_init+0x38/0x78
memblock_reserve: [0x41900000-0x41ffffff] early_init_fdt_scan_reserved_mem+0x64/0xa0
memblock_reserve: [0x42000000-0x420fffff] early_init_fdt_scan_reserved_mem+0x64/0xa0
memblock_reserve: [0x42100000-0x4210ffff] early_init_fdt_scan_reserved_mem+0x64/0xa0
memblock_reserve: [0x448df000-0x44cc6fff] early_init_fdt_scan_reserved_mem+0x64/0xa0
memblock_reserve: [0x47000000-0x47ffffff] memblock_alloc_range_nid+0xb0/0x128
...
...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

可以发现0x4210ffff0x448df000中间有一段空出的空间,所以取了0x43000000

参考文章

聊聊SOC启动(八) uboot启动流程三
覆盖设备树(Devices-tree overlays)

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号