Zephyr Devicetree 详解 Devicetree 覆盖
在 Zephyr Devicetree 详解-生成过程和结果 一文中提到过 Devicetree 覆盖文件 ( .overlay ) ,并简单介绍了其作用是针对板级 dts,新增/修改/禁用一些和硬件相关的功能。本文将详细说明如何设置和使用 Devicetree 覆盖文件。
设置 Devicetree 覆盖 链接到标题
在 CMake 变量 DTC_OVERLAY_FILE
中包含覆盖文件列表,文件之间以空格或分号分隔。如果 DTC_OVERLAY_FILE
指定多个文件,它们会按照指定的顺序被 C 预处理器包含。设置 DTC_OVERLAY_FILE
变量时,可以通过转义 Zephyr 模块目录变量 ( 例如${ZEPHYR_<module>_MODULE_DIR}/<path-to>/dts.overlay ) 来引用 Zephyr 模块中的文件。在 west build 的时候通过设置 DTC_OVERLAY_FILE
准确的指定使用的覆盖文件。 当需要指定多个覆盖文件时,请将文件列表用引号括起来,并用分号分隔每个文件名。例如
west build -b reel_board -- -DDTC_OVERLAY_FILE=enable-modem.overlay
west build -b reel_board -- -DDTC_OVERLAY_FILE="file1.overlay;file2.overlay"
覆盖文件的使用 链接到标题
如果未设置 DTC_OVERLAY_FILE
,构建系统将按下面步骤在应用程序配置目录 ( 由 APPLICATION_CONFIG_DIR
指定,没有指定就是应用程序的目录 ) 中查找覆盖文件
- 如果文件 socs/<SOC>.overlay 存在,则会使用该文件
- 如果文件 boards/<BOARD>.overlay 存在,附加使用它
- 如果当前板有[多个修订版]并且 boards/<BOARD>_<revision>.overlay 存在,除上述之外还会附近使用它
- 如果在前面的步骤中找到一个或多个文件,构建系统将停止查找并仅使用这些文件
- 否则,如果<BOARD>.overlay 存在,则使用它,并且构建系统将停止查找更多文件
- 否则,如果 app.overlay 存在,则会使用它
DTC_OVERLAY_FILE
或构建系统自动使用上述步骤中描述的覆盖生效后,EXTRA_DTC_OVERLAY_FILE
再提供额外的覆盖。- 如果使用 Shields 还将添加 Shields 的 Devicetree 覆盖文件
以上覆盖文件的生效留存如下图:
你可以根据上图和应用程序目录以及指定的 DTC_OVERLAY_FILE
和 EXTRA_DTC_OVERLAY_FILE
来判断最终有那些。overlay 会加入到覆盖。
例如有一个应用目录 ~/zephyr_samlpe
,与 Devicetree 相关的文件如下
.
├── app.overlay
├── boards
│ ├── esp32c3_zgp.overlay
│ └── halfcoder
│ ├── esp32c3_zgp
│ │ ├── esp32c3_zgp.dts
│ │ ├── esp32c3_zgp.overlay
├── cover.overlay
├── ext_cover.overlay
├── esp32c3_zgp.overlay
├── socs
│ └── esp32c3.overlay
- 执行
west build -b esp32c3_zgp ~/zephyr_sample
esp32c3_zgp.dts
+socs/esp32c3.overlay
+boards/esp32c3_zgp.overlay
- 执行
west build -b esp32c3_zgp ~/zephyr_sample -- -DDTC_OVERLAY_FILE=cover.overlay
esp32c3_zgp.dts
+cover.overlay
- 执行
west build -b esp32c3_zgp ~/zephyr_sample -- -DEXTRA_DTC_OVERLAY_FILE=ext_cover.overlay
esp32c3_zgp.dts
+socs/esp32c3.overlay
+boards/esp32c3_zgp.overlay
+ext_cover.overlay
- 执行
west build -b esp32c3_zgp ~/zephyr_sample -- -DDTC_OVERLAY_FILE=cover.overlay -DEXTRA_DTC_OVERLAY_FILE=ext_cover.overlay
esp32c3_zgp.dts
+cover.overlay
+ext_cover.overlay
构建过程中会打印找到的覆盖文件,可以通过该打印信息判断使用的覆盖文件是否符合预期:
-- Found Dtc: /home/frank/work/zpro/tools/zephyr-sdk-0.16.8/sysroots/x86_64-pokysdk-linux/usr/bin/dtc ( found suitable version "1.6.0", minimum required is "1.4.6" )
-- Found BOARD.dts: /home/frank/work/zpro/book_sample/zephyr_sample/boards/halfcoder/esp32c3_zgp/esp32c3_zgp.dts
-- Found devicetree overlay: /home/frank/work/zpro/book_sample/zephyr_sample/socs/esp32c3.overlay
-- Found devicetree overlay: /home/frank/work/zpro/book_sample/zephyr_sample/boards/esp32c3_zgp.overlay
-- Found devicetree overlay: cover.overlay
-- Generated zephyr.dts: /home/frank/work/zpro/book_sample/build/zephyr/zephyr.dts
覆盖文件的优先级 链接到标题
覆盖文件优先级由覆盖的顺序决定:谁后覆盖谁优先级高,覆盖的顺序见前面流程图。 例如:
esp32c3_zgp.dts
原本设置 uart0 的波特率为 115200cover.overlay
将 uart0 的波特率为 9600ext_cover.overlay
将 uart0 的波特率为 38400
按照 esp32c3_zgp.dts
+cover.overlay
+ext_cover.overlay
从前到后的顺序,最后 uart0 的波特率应为 38400
使用 Devicetree 覆盖 链接到标题
覆盖可以通过多种方式覆盖节点属性值。例如,如果 BOARD.dts 包含节点:
/ {
soc {
serial0: serial@40002000 {
status = "okay";
current-speed = <115200>;
/* ... */
};
};
};
下面是覆盖 current-speed
值的等效方法:
/* 使用 lable */
&serial0 {
current-speed = <9600>;
};
/* 使用节点全路径 */
&{/soc/serial@40002000} {
current-speed = <9600>;
};
为了简洁,我们更常使用 lable。
在覆盖文件中可以添加,覆盖,删除属性和子节点,例如下面是一个 board.dts
/ {
model = "esp32c3_zgp";
compatible = "espressif,esp32c3";
chosen {
zephyr,sram = &sram0;
zephyr,console = &uart0;
zephyr,uart-mcumgr=&uart0;
};
buttons: buttons {
compatible = "gpio-keys";
button0: button_0 {
gpios = <&gpio0 9 ( GPIO_PULL_UP | GPIO_ACTIVE_LOW )>;
label = "User SW1";
zephyr,code = <INPUT_KEY_0>;
};
};
}
&uart0 {
status = "okay";
current-speed = <115200>;
pinctrl-0 = <&uart0_default>;
pinctrl-names = "default";
};
&usb_serial {
/* requires resoldering of resistors on the board */
status = "okay";
};
&i2c0 {
status = "okay";
clock-frequency = <I2C_BITRATE_STANDARD>;
pinctrl-0 = <&i2c0_default>;
pinctrl-names = "default";
};
我用一个 cover.overlay 去覆盖,达到下面目的:
- 添加一个别名,
my-serial = &uart0;
- 将 uart1 启用,并修改 console 使用 uart1
- 修改 uart0 的默认波特率为 9600
- 删除
zephyr,uart-mcumgr
- 在 i2c0 下增加一个 bmg160 子节点
cover.overlay 的内容应该如下
/* 删除的内容也可以放到后面的/{chosen{}}内,但为了好辨认,通常会被集中到一起放在/{}下 */
/ {
chosen {
/*删除属性 zephyr,uart-mcumgr*/
/delete-property/ zephyr,uart-mcumgr;
};
};
/ {
chosen {
/* 修改属性 */
zephyr,console = &uart1;
/* /delete-property/ zephyr,uart-mcumgr; 也可以放到这里 */
};
aliases {
/* 添加别名 */
my-serial = &uart1;
};
};
/* 启用 uart1 */
&uart1 {
status = "okay";
};
/* 修改 uart0 的默认波特率 */
&uart0 {
current-speed = <9600>;
};
/* 在 i2c0 下添加节点 bmg160 */
&i2c0 {
bmg160@68 {
compatible = "bosch,bmg160";
reg = <0x68>;
int-gpios = <&gpioc 6 0>;
};
};
参考 链接到标题
https://docs.zephyrproject.org/latest/build/dts/howtos.html#set-devicetree-overlays https://docs.zephyrproject.org/latest/build/dts/howtos.html#use-devicetree-overlays