Zephyr v3.4.0 release中新增加了snippet功能,以此来简化原来对overlay配置文件和设备树的用法。
原来的overlay
Zephyr提供了对配置的文件和设备树的overlay,用于添加额外的配置选项,通常用于:
- 灵活的开启调试和释放版本
- 指定不同应用的配置选项
例如一般情况下编译应用zephyr_sample为释放版本:1
west build -b esp32c3_zgp zephyr_sample/
它会引用zephyr_sample/prj.conf作为配置项,引用esp32c3_zgp的board下的设备树。
当我们想开启debug模式的时候,可以建立debug.conf和debug.overlay,开启debug mode并将串口重定位到uart2上1
2
3# debug.conf
CONFIG_SHELL=y
CONFIG_DEBUG=y
1 | debug.overlay |
再采用如下方式重新编译就可以编译出debug版本的image1
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
如果全部开启就会变为1
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
下,提供了配置:1
2
3
4
5
6
7
8CONFIG_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
设备树的overlay1
2
3
4
5
6
7
8
9
10
11/ {
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这两个文件时只用执行1
west build -b mm_swiftio -S cdc-acm-console ./zephyr_sample
是不是比下面要简洁一些:1
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
1
2# west构建时会从/path1和/path2去查找snippet,也可以指定一个或者更多的路径
set(SNIPPET_ROOT "/path1;/path2")在app下建立snippets文件夹,并放置snippet
1
2
3
4
5
6
7
8└── zephyr_sample
├── CMakeLists.txt
├── Kconfig
├── boards
├── prj.conf
├── snippets
├── src
└── west.yml在外部module的module.yml中添加snippet_root
1
2settings:
snippet_root: .
对于应用来说通常我们用第二种方法
演示
例如我们要为zephyr_sample建立一个remap-uart的snippet,当使用改snippet时调试串口会指向到uart1
建立zephyr_sample的snippets文件夹
1
2└── zephyr_sample
├── snippets建立remap-uart文件
1
2
3
4└── remap-uart
├── remap-uart.conf
├── remap-uart.overlay
└── snippet.yml在snippet.yml中对snippet进行描述
1
2
3
4
5
6name: 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文件内容
1
2
3# remap-uart.conf
# 启用kernel shell
SHELL_KERNEL=y
1 | /* remap-uart.overlay */ |
5 使用
构建时加上-S remap-uart
后console和shell都通过uart输出1
west build -b esp32c2_zgp -S remap-uart ./zephyr_sampe
指定board
前面示例看到可以通过boards指定不同的board生效的不同的snippet,例如1
2
3
4
5
6
7
8
9
10name: 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,例如1
2
3
4
5
6name: remap-uart
boards:
/esp32c3_*/:
append:
EXTRA_CONF_FILE: remap-uart.conf
EXTRA_DTC_OVERLAY_FILE: remap-uart.overlay
还可以不指定board,对所有board都生效相同的snippet,例如1
2
3
4name: remap-uart
append:
EXTRA_CONF_FILE: remap-uart.conf
EXTRA_DTC_OVERLAY_FILE: remap-uart.overlay
多snippet
当我们制作了多个snippet,例如最前面的有wifi,eth,debug,那么构建的时候就使用1
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
如下1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17set(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