Zephyr 片段(snippet)配置功能使用说明
本文介绍说明Zephyr片段功能和使用方法。
Zephyr v3.4.0 release中新增加了snippet功能,以此来简化原来对overlay配置文件和设备树的用法。
原来的overlay 链接到标题
Zephyr提供了对配置的文件和设备树的overlay,用于添加额外的配置选项,通常用于:
- 灵活的开启调试和释放版本
- 指定不同应用的配置选项 例如一般情况下编译应用zephyr_sample为释放版本:
west build -b esp32c3_zgp zephyr_sample/
它会引用zephyr_sample/prj.conf作为配置项,引用esp32c3_zgp的board下的设备树。 当我们想开启debug模式的时候,可以建立debug.conf和debug.overlay,开启debug mode并将串口重定位到uart2上
# debug.conf
CONFIG_SHELL=y
CONFIG_DEBUG=y
debug.overlay
/ {
chosen {
zephyr,console = &uart2; /* 指定console使用uart1 */
zephyr,shell-uart = &uart2; /* 指定shell使用uart1*/
};
};
再采用如下方式重新编译就可以编译出debug版本的image
west build -b esp32c3_zgp zephyr_sample/ -- -DDTC_OVERLAY_FILE="debug.overlay" -DOVERLAY_CONFIG="debug.conf"
这样做可以不用来回修改prj.conf和board下面设备,但当有多应用功能时就会略显麻烦,例如:
- 使用wifi: wifi.conf, wifi.overlay
- 使用eth: eth.conf, eth.overlay
- 使用大尺寸flash: size.conf, size.overlay 如果全部开启就会变为
west build -b esp32c3_zgp zephyr_sample/ -- -DDTC_OVERLAY_FILE="wifi.overlay" -DDTC_OVERLAY_FILE="eth.overlay" -DDTC_OVERLAY_FILE="size.overlay" -DOVERLAY_CONFIG="wifi.conf" -DOVERLAY_CONFIG="eth.conf" -DOVERLAY_CONFIG="size.conf"
有两个问题(我是深有体会):
- 输入的命令太长
- 时间长了连命令都不记得了
snippet 链接到标题
zephyr v3.4.0引入了snippet可以简化overlay, 可以将snippet理解为替代overlay,一个snippet对应一组.conf和.overlay, 我们先看一组简单的使用方式:zephyr提供内置的cdc-acm-console snippet,放置在zephyr/snippets/cdc-acm-console下,提供了配置:
CONFIG_USB_DEVICE_STACK=y
CONFIG_USB_DEVICE_PRODUCT="Zephyr USB console sample"
CONFIG_USB_DEVICE_PID=0x0004
CONFIG_SERIAL=y
CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=y
CONFIG_UART_LINE_CTRL=y
设备树的overlay
/ {
chosen {
zephyr,console = &snippet_cdc_acm_console_uart;
};
};
&zephyr_udc0 {
snippet_cdc_acm_console_uart: snippet_cdc_acm_console_uart {
compatible = "zephyr,cdc-acm-uart";
};
};
当要overlay这两个文件时只用执行
west build -b mm_swiftio -S cdc-acm-console ./zephyr_sample
是不是比下面要简洁一些:
west build -b mm_swiftio zephyr_sample/ -- -DDTC_OVERLAY_FILE="cdc-acm-console.overlay" -DOVERLAY_CONFIG="cdc-acm-console.conf"
如何使用 链接到标题
snippet放置位置 链接到标题
在zephyr/snippets下可以增加新的snippet, 但这样会污染zephyr的主目录,同时如果只是为我们自己开发的应用使用也不方便代码管理,有两种方式
- 在app的CMakeList.txt中指定
SNIPPET_ROOT
# west构建时会从/path1和/path2去查找snippet,也可以指定一个或者更多的路径
set(SNIPPET_ROOT "/path1;/path2")
- 在app下建立snippets文件夹,并放置snippet
└── zephyr_sample
├── CMakeLists.txt
├── Kconfig
├── boards
├── prj.conf
├── snippets
├── src
└── west.yml
- 在外部module的module.yml中添加snippet_root
settings:
snippet_root: .
对于应用来说通常我们用第二种方法
演示 链接到标题
例如我们要为zephyr_sample建立一个remap-uart的snippet,当使用改snippet时调试串口会指向到uart1
- 建立zephyr_sample的snippets文件夹
└── zephyr_sample
├── snippets
- 建立remap-uart文件
└── remap-uart
├── remap-uart.conf
├── remap-uart.overlay
└── snippet.yml
- 在snippet.yml中对snippet进行描述
name: remap-uart
boards:
esp32c3_zgp:
append:
EXTRA_CONF_FILE: remap-uart.conf
EXTRA_DTC_OVERLAY_FILE: remap-uart.overlay
- name: snippet的名字
- boards: 对esp32c3_zgp这种开发板生效
- EXTRA_CONF_FILE: 配置文件
- EXTRA_DTC_OVERLAY_FILE: 设备树文件
- EXTRA_CONF_FILE/EXTRA_DTC_OVERLAY_FILE文件内容
# remap-uart.conf
# 启用kernel shell
SHELL_KERNEL=y
/* remap-uart.overlay */
/ {
chosen {
zephyr,console = &uart1; /* 指定console使用uart1 */
zephyr,shell-uart = &uart1; /* 指定shell使用uart1*/
};
};
/* 指定UART的pinctrl */
&pinctrl {
uart1_default: uart1_default {
group1 {
pinmux = <UART1_TX_GPIO4>;
output-high;
};
group2 {
pinmux = <UART1_RX_GPIO5>;
};
};
};
/* UART1的配置 */
&uart1 {
status = "okay";
current-speed = <115200>;
pinctrl-0 = <&uart1_default>;
pinctrl-names = "default";
};
5 使用
构建时加上-S remap-uart后console和shell都通过uart输出
west build -b esp32c2_zgp -S remap-uart ./zephyr_sampe
指定board 链接到标题
前面示例看到可以通过boards指定不同的board生效的不同的snippet,例如
name: remap-uart
boards:
esp32c3_zgp:
append:
EXTRA_CONF_FILE: remap-uart.conf
EXTRA_DTC_OVERLAY_FILE: remap-uart.overlay
esp32c3_devkit:
append:
EXTRA_CONF_FILE: remap-uart-kit.conf
EXTRA_DTC_OVERLAY_FILE: remap-uart-kit.overlay
也可以使用正则表达式指定同类的board生效相同的snippet,例如
name: remap-uart
boards:
/esp32c3_*/:
append:
EXTRA_CONF_FILE: remap-uart.conf
EXTRA_DTC_OVERLAY_FILE: remap-uart.overlay
还可以不指定board,对所有board都生效相同的snippet,例如
name: remap-uart
append:
EXTRA_CONF_FILE: remap-uart.conf
EXTRA_DTC_OVERLAY_FILE: remap-uart.overlay
多snippet 链接到标题
当我们制作了多个snippet,例如最前面的有wifi,eth,debug,那么构建的时候就使用
west build -b mm_swiftio -S wifi -S eth -s debug ./zephyr_sampe
实现分析指引 链接到标题
zephyr/scripts/west_commands/build.py 收集-S参数加入到-DSNIPPET中
zephyr/cmake/modules/zephyr_default.cmake 使用list(APPEND zephyr_cmake_modules snippets) 加载zephyr\cmake\modules\snippets.cmake执行zephyr_process_snippets
zephyr_process_snippets查找SNIPPET_ROOT并根据-DSNIPPET生成requested_snippet_args
zephyr_process_snippets调用zephyr/scripts/snippets.py将requested_snippet_args转化为build\zephyr\snippets_generated.cmake
snippets_generated.cmake中设置EXTRA_CONF_FILE和EXTRA_DTC_OVERLAY_FILE
zephyr/cmake/modules/kconfig.cmake引用EXTRA_CONF_FILE
zephyr/cmake/modules/dts.cmake引用EXTRA_DTC_OVERLAY_FILE
例如remap-uart例子中生成的snippets_generated.cmake如下
set(SNIPPET_NAMES "cdc-acm-console" "remap-uart")
# The paths to all the snippet.yml files. One snippet
# can have multiple snippet.yml files.
set(SNIPPET_PATHS "/mnt/e/book/sample/zephyr/snippets/cdc-acm-console/snippet.yml" "/mnt/e/book/sample/zephyr_sample/snippets/remap-uart/snippet.yml")
# Create variable scope for snippets build variables
zephyr_create_scope(snippets)
###############################################################################
# Snippet 'remap-uart'
# Common variable appends.
# Appends for board 'esp32c3_zgp'
if("${BOARD}" STREQUAL "esp32c3_zgp")
zephyr_set(EXTRA_CONF_FILE "/mnt/e/book/sample/zephyr_sample/snippets/remap-uart/remap-uart.conf" SCOPE snippets APPEND)
zephyr_set(EXTRA_DTC_OVERLAY_FILE "/mnt/e/book/sample/zephyr_sample/snippets/remap-uart/remap-uart.overlay" SCOPE snippets APPEND)
endif()
参考 链接到标题
https://docs.zephyrproject.org/latest/build/snippets/index.html