190 lines · plain
1.. SPDX-License-Identifier: GPL-2.02.. include:: ../disclaimer-zh_CN.rst3 4:Original: Documentation/devicetree/of_unittest.rst5 6:翻译:7 8 司延腾 Yanteng Si <siyanteng@loongson.cn>9 10:校译:11 12=================================13Open Firmware Devicetree 单元测试14=================================15 16作者: Gaurav Minocha <gaurav.minocha.os@gmail.com>17 181. 概述19=======20 21本文档解释了执行 OF 单元测试所需的测试数据是如何动态地附加到实时树上的,与机器的架构无关。22 23建议在继续读下去之前,先阅读以下文件。24 25(1) Documentation/devicetree/usage-model.rst26(2) http://www.devicetree.org/Device_Tree_Usage27 28OF Selftest被设计用来测试提供给设备驱动开发者的接口(include/linux/of.h),以从未扁平29化的设备树数据结构中获取设备信息等。这个接口被大多数设备驱动在各种使用情况下使用。30 31 322. 测试数据33===========34 35设备树源文件(drivers/of/unittest-data/testcases.dts)包含执行drivers/of/unittest.c36中自动化单元测试所需的测试数据。目前,以下设备树源包含文件(.dtsi)被包含在testcases.dt中::37 38 drivers/of/unittest-data/tests-interrupts.dtsi39 drivers/of/unittest-data/tests-platform.dtsi40 drivers/of/unittest-data/tests-phandle.dtsi41 drivers/of/unittest-data/tests-match.dtsi42 43当内核在启用OF_SELFTEST的情况下被构建时,那么下面的make规则::44 45 $(obj)/%.dtb: $(src)/%.dts FORCE46 $(call if_changed_dep, dtc)47 48用于将DT源文件(testcases.dts)编译成二进制blob(testcases.dtb),也被称为扁平化的DT。49 50之后,使用以下规则将上述二进制blob包装成一个汇编文件(testcases.dtb.S)::51 52 $(obj)/%.dtb.S: $(obj)/%.dtb53 $(call cmd, dt_S_dtb)54 55汇编文件被编译成一个对象文件(testcases.dtb.o),并被链接到内核镜像中。56 57 582.1. 添加测试数据59-----------------60 61未扁平化的设备树结构体:62 63未扁平化的设备树由连接的设备节点组成,其树状结构形式如下所述::64 65 // following struct members are used to construct the tree66 struct device_node {67 ...68 struct device_node *parent;69 struct device_node *child;70 struct device_node *sibling;71 ...72 };73 74图1描述了一个机器的未扁平化设备树的通用结构,只考虑了子节点和同级指针。存在另一个指针,75``*parent`` ,用于反向遍历该树。因此,在一个特定的层次上,子节点和所有的兄弟姐妹节点将76有一个指向共同节点的父指针(例如,child1、sibling2、sibling3、sibling4的父指针指向77根节点)::78 79 root ('/')80 |81 child1 -> sibling2 -> sibling3 -> sibling4 -> null82 | | | |83 | | | null84 | | |85 | | child31 -> sibling32 -> null86 | | | |87 | | null null88 | |89 | child21 -> sibling22 -> sibling23 -> null90 | | | |91 | null null null92 |93 child11 -> sibling12 -> sibling13 -> sibling14 -> null94 | | | |95 | | | null96 | | |97 null null child131 -> null98 |99 null100 101Figure 1: 未扁平化的设备树的通用结构102 103 104在执行OF单元测试之前,需要将测试数据附加到机器的设备树上(如果存在)。因此,当调用105selftest_data_add()时,首先会读取通过以下内核符号链接到内核镜像中的扁平化设备树106数据::107 108 __dtb_testcases_begin - address marking the start of test data blob109 __dtb_testcases_end - address marking the end of test data blob110 111其次,它调用of_fdt_unflatten_tree()来解除扁平化的blob。最后,如果机器的设备树112(即实时树)是存在的,那么它将未扁平化的测试数据树附加到实时树上,否则它将自己作为113实时设备树附加。114 115attach_node_and_children()使用of_attach_node()将节点附加到实时树上,如下所116述。为了解释这一点,图2中描述的测试数据树被附加到图1中描述的实时树上::117 118 root ('/')119 |120 testcase-data121 |122 test-child0 -> test-sibling1 -> test-sibling2 -> test-sibling3 -> null123 | | | |124 test-child01 null null null125 126 127Figure 2: 将测试数据树附在实时树上的例子。128 129根据上面的方案,实时树已经存在,所以不需要附加根('/')节点。所有其他节点都是通过在130每个节点上调用of_attach_node()来附加的。131 132在函数of_attach_node()中,新的节点被附在实时树中给定的父节点的子节点上。但是,如133果父节点已经有了一个孩子,那么新节点就会取代当前的孩子,并将其变成其兄弟姐妹。因此,134当测试案例的数据节点被连接到上面的实时树(图1)时,最终的结构如图3所示::135 136 root ('/')137 |138 testcase-data -> child1 -> sibling2 -> sibling3 -> sibling4 -> null139 | | | | |140 (...) | | | null141 | | child31 -> sibling32 -> null142 | | | |143 | | null null144 | |145 | child21 -> sibling22 -> sibling23 -> null146 | | | |147 | null null null148 |149 child11 -> sibling12 -> sibling13 -> sibling14 -> null150 | | | |151 null null | null152 |153 child131 -> null154 |155 null156 -----------------------------------------------------------------------157 158 root ('/')159 |160 testcase-data -> child1 -> sibling2 -> sibling3 -> sibling4 -> null161 | | | | |162 | (...) (...) (...) null163 |164 test-sibling3 -> test-sibling2 -> test-sibling1 -> test-child0 -> null165 | | | |166 null null null test-child01167 168 169Figure 3: 附加测试案例数据后的实时设备树结构。170 171 172聪明的读者会注意到,与先前的结构相比,test-child0节点成为最后一个兄弟姐妹(图2)。173在连接了第一个test-child0节点之后,又连接了test-sibling1节点,该节点推动子节点174(即test-child0)成为兄弟姐妹,并使自己成为子节点,如上所述。175 176如果发现一个重复的节点(即如果一个具有相同full_name属性的节点已经存在于实时树中),177那么该节点不会被附加,而是通过调用函数update_node_properties()将其属性更新到活178树的节点中。179 180 1812.2. 删除测试数据182-----------------183 184一旦测试用例执行完,selftest_data_remove被调用,以移除最初连接的设备节点(首先是185叶子节点被分离,然后向上移动父节点被移除,最后是整个树)。selftest_data_remove()186调用detach_node_and_children(),使用of_detach_node()将节点从实时设备树上分离。187 188为了分离一个节点,of_detach_node()要么将给定节点的父节点的子节点指针更新为其同级节189点,要么根据情况将前一个同级节点附在给定节点的同级节点上。就这样吧。 :)190