.. SPDX-License-Identifier: GPL-2.0 .. include:: ../disclaimer-zh_CN.rst :Original: Documentation/devicetree/of_unittest.rst :翻译: å¸å»¶è…¾ Yanteng Si <siyanteng@loongson.cn> :æ ¡è¯‘: ================================= Open Firmware Devicetree å•å…ƒæµ‹è¯• ================================= 作者: Gaurav Minocha <gaurav.minocha.os@gmail.com> 1. 概述 ======= 本文档解释了执行 OF å•å…ƒæµ‹è¯•æ‰€éœ€çš„测试数æ®æ˜¯å¦‚何动æ€åœ°é™„åŠ åˆ°å®žæ—¶æ ‘ä¸Šçš„ï¼Œä¸Žæœºå™¨çš„æž¶æž„æ— å…³ã€‚ 建议在继ç»è¯»ä¸‹åŽ»ä¹‹å‰ï¼Œå…ˆé˜…读以下文件。 (1) Documentation/devicetree/usage-model.rst (2) http://www.devicetree.org/Device_Tree_Usage OF Selftest被设计用æ¥æµ‹è¯•æ供给设备驱动开å‘者的接å£ï¼ˆinclude/linux/of.h),以从未æ‰å¹³ åŒ–çš„è®¾å¤‡æ ‘æ•°æ®ç»“æž„ä¸èŽ·å–设备信æ¯ç‰ã€‚这个接å£è¢«å¤§å¤šæ•°è®¾å¤‡é©±åŠ¨åœ¨å„ç§ä½¿ç”¨æƒ…况下使用。 2. æµ‹è¯•æ•°æ® =========== è®¾å¤‡æ ‘æºæ–‡ä»¶ï¼ˆdrivers/of/unittest-data/testcases.dts)包å«æ‰§è¡Œdrivers/of/unittest.c ä¸è‡ªåŠ¨åŒ–å•å…ƒæµ‹è¯•æ‰€éœ€çš„测试数æ®ã€‚ç›®å‰ï¼Œä»¥ä¸‹è®¾å¤‡æ ‘æºåŒ…å«æ–‡ä»¶ï¼ˆ.dtsi)被包å«åœ¨testcases.dtä¸:: drivers/of/unittest-data/tests-interrupts.dtsi drivers/of/unittest-data/tests-platform.dtsi drivers/of/unittest-data/tests-phandle.dtsi drivers/of/unittest-data/tests-match.dtsi å½“å†…æ ¸åœ¨å¯ç”¨OF_SELFTEST的情况下被构建时,那么下é¢çš„make规则:: $(obj)/%.dtb: $(src)/%.dts FORCE $(call if_changed_dep, dtc) 用于将DTæºæ–‡ä»¶ï¼ˆtestcases.dts)编译æˆäºŒè¿›åˆ¶blob(testcases.dtb),也被称为æ‰å¹³åŒ–çš„DT。 之åŽï¼Œä½¿ç”¨ä»¥ä¸‹è§„则将上述二进制blob包装æˆä¸€ä¸ªæ±‡ç¼–文件(testcases.dtb.S):: $(obj)/%.dtb.S: $(obj)/%.dtb $(call cmd, dt_S_dtb) 汇编文件被编译æˆä¸€ä¸ªå¯¹è±¡æ–‡ä»¶ï¼ˆtestcases.dtb.oï¼‰ï¼Œå¹¶è¢«é“¾æŽ¥åˆ°å†…æ ¸é•œåƒä¸ã€‚ 2.1. æ·»åŠ æµ‹è¯•æ•°æ® ----------------- 未æ‰å¹³åŒ–çš„è®¾å¤‡æ ‘ç»“æž„ä½“: 未æ‰å¹³åŒ–çš„è®¾å¤‡æ ‘ç”±è¿žæŽ¥çš„è®¾å¤‡èŠ‚ç‚¹ç»„æˆï¼Œå…¶æ ‘状结构形å¼å¦‚下所述:: // following struct members are used to construct the tree struct device_node { ... struct device_node *parent; struct device_node *child; struct device_node *sibling; ... }; 图1æ述了一个机器的未æ‰å¹³åŒ–è®¾å¤‡æ ‘çš„é€šç”¨ç»“æž„ï¼Œåªè€ƒè™‘了å节点和åŒçº§æŒ‡é’ˆã€‚å˜åœ¨å¦ä¸€ä¸ªæŒ‡é’ˆï¼Œ ``*parent`` ,用于åå‘éåŽ†è¯¥æ ‘ã€‚å› æ¤ï¼Œåœ¨ä¸€ä¸ªç‰¹å®šçš„层次上,å节点和所有的兄弟å§å¦¹èŠ‚点将 有一个指å‘å…±åŒèŠ‚点的父指针(例如,child1ã€sibling2ã€sibling3ã€sibling4çš„çˆ¶æŒ‡é’ˆæŒ‡å‘ æ ¹èŠ‚ç‚¹ï¼‰:: root ('/') | child1 -> sibling2 -> sibling3 -> sibling4 -> null | | | | | | | null | | | | | child31 -> sibling32 -> null | | | | | | null null | | | child21 -> sibling22 -> sibling23 -> null | | | | | null null null | child11 -> sibling12 -> sibling13 -> sibling14 -> null | | | | | | | null | | | null null child131 -> null | null Figure 1: 未æ‰å¹³åŒ–çš„è®¾å¤‡æ ‘çš„é€šç”¨ç»“æž„ 在执行OFå•å…ƒæµ‹è¯•ä¹‹å‰ï¼Œéœ€è¦å°†æµ‹è¯•æ•°æ®é™„åŠ åˆ°æœºå™¨çš„è®¾å¤‡æ ‘ä¸Šï¼ˆå¦‚æžœå˜åœ¨ï¼‰ã€‚å› æ¤ï¼Œå½“调用 selftest_data_add()时,首先会读å–é€šè¿‡ä»¥ä¸‹å†…æ ¸ç¬¦å·é“¾æŽ¥åˆ°å†…æ ¸é•œåƒä¸çš„æ‰å¹³åŒ–è®¾å¤‡æ ‘ æ•°æ®:: __dtb_testcases_begin - address marking the start of test data blob __dtb_testcases_end - address marking the end of test data blob 其次,它调用of_fdt_unflatten_tree()æ¥è§£é™¤æ‰å¹³åŒ–çš„blob。最åŽï¼Œå¦‚æžœæœºå™¨çš„è®¾å¤‡æ ‘ (å³å®žæ—¶æ ‘)是å˜åœ¨çš„,那么它将未æ‰å¹³åŒ–的测试数æ®æ ‘é™„åŠ åˆ°å®žæ—¶æ ‘ä¸Šï¼Œå¦åˆ™å®ƒå°†è‡ªå·±ä½œä¸º å®žæ—¶è®¾å¤‡æ ‘é™„åŠ ã€‚ attach_node_and_children()使用of_attach_node()å°†èŠ‚ç‚¹é™„åŠ åˆ°å®žæ—¶æ ‘ä¸Šï¼Œå¦‚ä¸‹æ‰€ 述。为了解释这一点,图2ä¸æ述的测试数æ®æ ‘è¢«é™„åŠ åˆ°å›¾1ä¸æè¿°çš„å®žæ—¶æ ‘ä¸Š:: root ('/') | testcase-data | test-child0 -> test-sibling1 -> test-sibling2 -> test-sibling3 -> null | | | | test-child01 null null null Figure 2: 将测试数æ®æ ‘é™„åœ¨å®žæ—¶æ ‘ä¸Šçš„ä¾‹å。 æ ¹æ®ä¸Šé¢çš„æ–¹æ¡ˆï¼Œå®žæ—¶æ ‘å·²ç»å˜åœ¨ï¼Œæ‰€ä»¥ä¸éœ€è¦é™„åŠ æ ¹('/')节点。所有其他节点都是通过在 æ¯ä¸ªèŠ‚点上调用of_attach_node()æ¥é™„åŠ çš„ã€‚ 在函数of_attach_node()ä¸ï¼Œæ–°çš„èŠ‚ç‚¹è¢«é™„åœ¨å®žæ—¶æ ‘ä¸ç»™å®šçš„父节点的å节点上。但是,如 果父节点已ç»æœ‰äº†ä¸€ä¸ªå©å,那么新节点就会å–代当å‰çš„å©å,并将其å˜æˆå…¶å…„弟å§å¦¹ã€‚å› æ¤ï¼Œ 当测试案例的数æ®èŠ‚点被连接到上é¢çš„å®žæ—¶æ ‘ï¼ˆå›¾1)时,最终的结构如图3所示:: root ('/') | testcase-data -> child1 -> sibling2 -> sibling3 -> sibling4 -> null | | | | | (...) | | | null | | child31 -> sibling32 -> null | | | | | | null null | | | child21 -> sibling22 -> sibling23 -> null | | | | | null null null | child11 -> sibling12 -> sibling13 -> sibling14 -> null | | | | null null | null | child131 -> null | null ----------------------------------------------------------------------- root ('/') | testcase-data -> child1 -> sibling2 -> sibling3 -> sibling4 -> null | | | | | | (...) (...) (...) null | test-sibling3 -> test-sibling2 -> test-sibling1 -> test-child0 -> null | | | | null null null test-child01 Figure 3: é™„åŠ æµ‹è¯•æ¡ˆä¾‹æ•°æ®åŽçš„å®žæ—¶è®¾å¤‡æ ‘ç»“æž„ã€‚ èªæ˜Žçš„读者会注æ„到,与先å‰çš„结构相比,test-child0节点æˆä¸ºæœ€åŽä¸€ä¸ªå…„弟å§å¦¹ï¼ˆå›¾2)。 在连接了第一个test-child0节点之åŽï¼Œåˆè¿žæŽ¥äº†test-sibling1节点,该节点推动å节点 (å³test-child0)æˆä¸ºå…„弟å§å¦¹ï¼Œå¹¶ä½¿è‡ªå·±æˆä¸ºå节点,如上所述。 如果å‘现一个é‡å¤çš„节点(å³å¦‚果一个具有相åŒfull_name属性的节点已ç»å˜åœ¨äºŽå®žæ—¶æ ‘ä¸ï¼‰ï¼Œ 那么该节点ä¸ä¼šè¢«é™„åŠ ï¼Œè€Œæ˜¯é€šè¿‡è°ƒç”¨å‡½æ•°update_node_properties()将其属性更新到活 æ ‘çš„èŠ‚ç‚¹ä¸ã€‚ 2.2. åˆ é™¤æµ‹è¯•æ•°æ® ----------------- 一旦测试用例执行完,selftest_data_remove被调用,以移除最åˆè¿žæŽ¥çš„设备节点(首先是 å¶å节点被分离,然åŽå‘上移动父节点被移除,最åŽæ˜¯æ•´ä¸ªæ ‘)。selftest_data_remove() 调用detach_node_and_children(),使用of_detach_node()å°†èŠ‚ç‚¹ä»Žå®žæ—¶è®¾å¤‡æ ‘ä¸Šåˆ†ç¦»ã€‚ 为了分离一个节点,of_detach_node()è¦ä¹ˆå°†ç»™å®šèŠ‚点的父节点的å节点指针更新为其åŒçº§èŠ‚ 点,è¦ä¹ˆæ ¹æ®æƒ…况将å‰ä¸€ä¸ªåŒçº§èŠ‚点附在给定节点的åŒçº§èŠ‚ç‚¹ä¸Šã€‚å°±è¿™æ ·å§ã€‚ :)