ZYNQ设备树覆盖(device-tree overlay)

        传统的设备树一般用于硬件资源已经确定的情况,但如果要添加或者删除硬件资源,需要找出已经在设备中使用的设备树源文件然后在源文件上修改,内核为了解决这个问题,就提出了Device Tree Overlays,中文上可以理解为“设备树插件”。其核心是通过传统的设备树语法,使得各个硬件模块的信息可以独立地用新的设备树语法来描述。在系统实际使用时,根据实际应用情景,需要用到哪些硬件模块就把对应的设备树插件加入到主设备树即可。

一、编译内核

在编译内核的过程中要启动`CONFIG_OF_OVERLAY`选项,否则即使尝试应用程序覆盖,内核也不会处理。

Zynq FPGA Manager Configuration:

Select: Device Drivers ---> FPGA Configuration Framework

DT overlay ConfigFS interface Configuration:

This is required only if the user is using to the Bitstream using DTO

Select: Device Drivers --> Device Tree and Open Firmware support

二、生成bitstream.bit.bin

使用bootgen工具和vivado生成的bitstream.bit文件生成bitstream.bit.bin

具体操作参考zynq的U-Boot加载fpga比特流文件_配置u-boot加载bit-CSDN博客中的第二点。

三、生成dtbo文件

1、使用vitis生成pl.dtsi文件:

下载和vitis版本对应的device-tree-xlnx文件(下载地址:https://github.com/Xilinx/device-tree-xlnx/tags):

点击vitis菜单栏"Xilinx -> Reposistories"。导入device-tree-xlnx源码:

注意:选择device-tree-xlnx版本和vitis版本一致

导入之后“Apply and Close”,然后“Create Platform Project”——>输入“Platform project name”

——>选择对应的.xsa文件,“Poerating system”选择“device_tree”

修改板级支持包,将dt_overlay的值总false改为ture

修改pl.dtsi文件

2、生成dtbo文件

在合适目录下创建文件夹device-tree-xlnx文件夹,并将之前生成的pl.dtsi文件copy到该文件夹

找到内核源码中的dtc工具,并记录当前目录:

在devie-tree-xlnx目录下使用源码目录下的dtc对pl.dtsi进行编译

/home/zy/linux-1/scripts/dtc/dtc -q -@ -O dtb -o pl.dtbo pl.dtsi

四、Apply dtbo文件

进入开发板系统执行指令新建“/lib/firmware”目录,将生成的pl.dtbo和system.bit.bin文件复制到“/lib/firmware”目录

创建configfs目录及设备节点:

mkdir /configfs //创建configfs目录

执行以下指令实现设备树的覆盖:

mount -t configfs configfs /configfs
mkdir /configfs/device-tree/overlays/full
echo -n "pl.dtbo" >  /configfs/device-tree/overlays/full/path

运行结果

出现报错:

no symbols in root of device tree

overlay phandle fixup failed: -22

五、报错及解决

devicetree overlay其实就是用pl.dtbo(覆盖设备树)文件去对devicetree.dts(基础设备树)打补丁,将pl端生成的设备补充到devicetree.dts里,这就要求pl.dtbo能够和devicetree.dts能够匹配。而设备树的节点之间是通过标签来引用的

<& 标签名>

引用节点的格式就是上面这样,我的理解是类似函数的调用。

	fragment@0 {
		target = <&fpga_full>;
		overlay0: __overlay__ {
			#address-cells = <2>;
			#size-cells = <2>;
			firmware-name = "system.bit.bin";
		};
	};

比如在这段代码中,target = <&fpga_full>; 就是在引用基础设备树的fpga_full标签。

----------------------------------------------------------分割线--------------------------------------------------------------

回到报错:no symbols in root of device tree

翻译过来就是在基础设备树中没有找到symbols字段,打开我的基础设备树查看是否有类似的symbols字段:

	__symbols__ {
		cpus = "/cpus";
		fpga_full = "/fpga-full";
		pmu = "/pmu@f8891000";
		fixedregulator = "/fixedregulator";
		amba = "/amba";
		clkc = "/amba/clkc@0";
		intc = "/amba/interrupt-controller@0";
		clkc_ps7_clkc = "/amba/slcr@f8000000/clkc@100";
		aliases = "/aliases";
		memory = "/memory";
		chosen = "/chosen";
		leds = "/leds";
		gpio_keys = "/gpio_keys";
		fpga_axi = "/fpga-axi@0";
		audio_clock = "/audio_clock";
		adv7511_hdmi_snd = "/adv7511_hdmi_snd";
		clocks = "/clocks";
		jesd_Tx_axi_0 = "/jesd_Tx@44a20000";
		jesd_Rx_axi_0 = "/jesd_Rx@44a00000";
	};

检查之后发现没有symbols字段,所以出现了报错“no symbols in root of device tree”。

搞清楚symbols字段的来源:symbols字段是基础设备树devicetree.dts中的标签,使用带@的指令

dtc -O dtb -o devicetree.dtb -b 0 -@ devicetree.dts

进行编译后得到devicetree.dtb文件,再用如下指令将dtb文件反编译成dts文件之后,才会出现symbols字段

dtc -I dtb -O dts -o devicetree.dts devicetree.dtb

也就是说,“no symbols in root of device tree”这个报错的原因:

1、可能是编译设备树的指令不带@

2、可能是dts设备树源码没有添加标签

换句话说,只要给dts设备树源码加上标签,并且用带@的指令编译设备树,就不会出现“no symbols”的报错

1、解决第一个报错

给节点添加标签的方式非常简单,比如

基础设备树中的一个节点:
fpga-full {
        compatible = "fpga-region";
        fpga-mgr = <0x00000004>;
        #address-cells = <0x00000001>;
        #size-cells = <0x00000001>;
        ranges;
}
覆盖设备树中的一个节点:
target = <&fpga_full>;
		overlay0: __overlay__ {
			#address-cells = <2>;
			#size-cells = <2>;
			firmware-name = "system.bit.bin";
		};

覆盖设备树中的target = <&fgpa_full>引用了基础设备树中的节点fpga_full,因此要给基础设备树中的fpga-full添加节点fpga_full:

fpga_full: fpga-full {
        compatible = "fpga-region";
        fpga-mgr = <0x00000004>;
        #address-cells = <0x00000001>;
        #size-cells = <0x00000001>;
        ranges;
    };

标签的名称必须和target = <& 标签名>中的标签名一致

将所有的target引用的节点都在基础设备树中找到,并添加对应标签之后用带@的指令进行编译。

之后我的运行结果依然会出现第二个报错:overlay phandle fixup failed: -22

2、解决第二个报错

第二个报错是因为基础设备树和覆盖设备树的phandle(point handle)不匹配,所以无法进行覆盖。其原因还是基础设备树和覆盖设备树的标签不匹配。

axi_gpio_0: gpio@41200000 {
				#gpio-cells = <3>;
				clock-names = "s_axi_aclk";
				clocks = <&clkc 15>;
				compatible = "xlnx,axi-gpio-2.0", "xlnx,xps-gpio-1.00.a";
				gpio-controller ;
				reg = <0x41200000 0x10000>;
				xlnx,all-inputs = <0x0>;
				xlnx,all-inputs-2 = <0x0>;
				xlnx,all-outputs = <0x0>;
				xlnx,all-outputs-2 = <0x0>;
				xlnx,dout-default = <0x00000000>;
				xlnx,dout-default-2 = <0x00000000>;
				xlnx,gpio-width = <0x1>;
				xlnx,gpio2-width = <0x20>;
				xlnx,interrupt-present = <0x0>;
				xlnx,is-dual = <0x0>;
				xlnx,tri-default = <0xFFFFFFFF>;
				xlnx,tri-default-2 = <0xFFFFFFFF>;
			};

比如clocks = <&clkc 15>;是调用了clkc 节点的第15个通道作为时钟输入 ,而我的基础设备树中并没有clkc这个节点,也就没有clkc这个标签 ,所以要在我的基础设备树中添加一个带clkc标签的 clkc节点(这个节点被添加到了amba节点下):

clkc: clkc@0 {
            compatible = "xlnx,clk-wiz";
            reg = <0x0 0x0 0x1000>;
            #clock-cells = <1>;
            clocks = <&clkc_ps7_clkc 16>; //是系统时钟clkc_ps7_clkcn fclk0 的索引
            clock-output-names = "clk_out1", "clk_out2", "clk_out3", "clk_out4", 
                         "clk_out5", "clk_out6", "clk_out7", "clk_out8",
                         "clk_out9", "clk_out10", "clk_out11", "clk_out12", 
                         "clk_out13", "clk_out14", "clk_out15", "clk_out16";
        };

因为我的需求只需要gpio和bram这两个设备,所以就把其他的节点都删除了。添加完节点之后,编译运行就没有出现报错了。

六、结果

参考链接:

覆盖设备树(Devices-tree overlays)_设备树overlay-CSDN博客

生成PL设备树及动态加载PL程序和设备树_pl文件怎么生成-CSDN博客

设备树知识小全(六):设备节点及label的命名_设备树节点名字:-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值